uni-app 入门学习教程,从入门到精通,uni-app 企业项目实战:鲁嗑瓜子项目开发知识点(9)
uni-app 企业项目实战:鲁嗑瓜子项目开发知识点详解
一、项目初始化与环境搭建
1.1 安装 HBuilderX(推荐 IDE)
步骤:
- 访问 DCloud 官网
- 下载 HBuilderX 标准版(支持 uni-app)
- 安装后打开,登录 DCloud 账号(用于云打包)
注意:不要使用 HBuilder(老版),必须用 HBuilderX。
1.2 创建 uni-app 项目
操作步骤:
- 打开 HBuilderX → 文件 → 新建 → 项目
- 选择模板:
uni-app - 项目名称:
luke-guazi - 模板选择:
默认模板或hello uni-app
项目结构说明:
luke-guazi/
├── pages/ # 页面目录
├── static/ # 静态资源(图片、字体等)
├── App.vue # 应用配置
├── main.js # 入口文件
├── manifest.json # App 配置(名称、图标、权限等)
├── pages.json # 页面路由与窗口样式配置
└── uni.scss # 全局样式变量
二、首页静态页面布局
2.1 使用 Flex 布局搭建首页结构
知识点:
flex-directionjustify-contentalign-itemsrpx单位(响应式像素)
案例代码:pages/index/index.vue
<template><view class="container"><!-- 顶部搜索栏 --><view class="search-bar"><input type="text" placeholder="搜索瓜子、坚果..." class="search-input" /></view><!-- 轮播图区域 --><view class="swiper-container"><!-- 后续动态渲染 --></view><!-- 广告板块 --><view class="ad-section"><image src="/static/ad1.jpg" mode="widthFix" class="ad-img"></image></view><!-- 商家推荐 --><view class="recommend-section"><text class="section-title">商家推荐</text><view class="merchant-list"><!-- 动态渲染 --></view></view><!-- 其他板块(如热销、新品等) --><view class="other-section"><text class="section-title">热销商品</text><!-- 商品列表 --></view></view>
</template><style scoped>
.container {padding: 20rpx;background-color: #f5f5f5;
}
.search-bar {display: flex;justify-content: center;margin-bottom: 20rpx;
}
.search-input {width: 90%;height: 60rpx;border-radius: 30rpx;background: #fff;padding: 0 30rpx;font-size: 28rpx;
}
.section-title {font-size: 32rpx;font-weight: bold;margin: 20rpx 0;display: block;
}
.ad-img {width: 100%;border-radius: 10rpx;
}
</style>
三、调用数据接口渲染轮播图
3.1 配置网络请求(uni.request)
知识点:
uni.request()发起 HTTP 请求onLoad生命周期钩子v-for循环渲染
接口假设:
GET https://api.lukeguazi.com/banner/list
返回格式:
{"code": 200,"data": [{ "id": 1, "imgUrl": "https://xxx/banner1.jpg" },{ "id": 2, "imgUrl": "https://xxx/banner2.jpg" }]
}
案例代码:
<script>
export default {data() {return {bannerList: [] // 存储轮播图数据}},onLoad() {this.loadBannerData();},methods: {async loadBannerData() {uni.showLoading({ title: '加载中...' });try {const res = await uni.request({url: 'https://api.lukeguazi.com/banner/list',method: 'GET'});// 解构响应const [error, response] = res;if (error || response.statusCode !== 200) {uni.showToast({ title: '加载失败', icon: 'none' });return;}if (response.data.code === 200) {this.bannerList = response.data.data;} else {uni.showToast({ title: '数据异常', icon: 'none' });}} catch (e) {console.error('请求异常:', e);uni.showToast({ title: '网络错误', icon: 'none' });} finally {uni.hideLoading();}}}
}
</script><template><view class="swiper-container"><swiper indicator-dots autoplay interval="3000" duration="500"circularstyle="height: 300rpx;"><swiper-item v-for="(item, index) in bannerList" :key="item.id"><image :src="item.imgUrl" mode="aspectFill" style="width:100%;height:100%;"></image></swiper-item></swiper></view>
</template>
注意:uni.request 返回的是
[error, response]数组(Promise 封装后需解构)。
四、首页广告板块 & 商家推荐数据渲染
4.1 广告板块(单图)
<!-- 假设广告数据来自接口 /ad/home -->
<script>
export default {data() {return {adImg: ''}},async onLoad() {const res = await uni.request({ url: 'https://api.lukeguazi.com/ad/home' });const [err, resp] = res;if (!err && resp.data.code === 200) {this.adImg = resp.data.data.imageUrl;}}
}
</script><template><view class="ad-section" v-if="adImg"><image :src="adImg" mode="widthFix" class="ad-img"></image></view>
</template>
4.2 商家推荐(列表)
<script>
export default {data() {return {merchants: []}},async onLoad() {const res = await uni.request({ url: 'https://api.lukeguazi.com/merchant/recommend' });const [err, resp] = res;if (!err && resp.data.code === 200) {this.merchants = resp.data.data;}}
}
</script><template><view class="merchant-list"><view v-for="item in merchants" :key="item.id" class="merchant-item"><image :src="item.logo" class="logo"></image><text class="name">{{ item.name }}</text></view></view>
</template><style scoped>
.merchant-item {display: flex;align-items: center;padding: 20rpx 0;border-bottom: 1rpx solid #eee;
}
.logo {width: 80rpx;height: 80rpx;border-radius: 50%;margin-right: 20rpx;
}
.name {font-size: 28rpx;
}
</style>
五、产品列表页开发
5.1 静态布局(含筛选区)
<template><view class="product-list"><!-- 筛选区 --><view class="filter-bar"><view @click="sortByPrice" class="filter-item">价格 {{ priceOrder === 'asc' ? '↑' : '↓' }}</view><view @click="openPriceRange" class="filter-item">价格区间</view></view><!-- 商品列表 --><view class="product-grid"><view v-for="product in productList" :key="product.id" class="product-card"><image :src="product.cover" class="cover"></image><text class="title">{{ product.name }}</text><text class="price">¥{{ product.price }}</text></view></view></view>
</template>
5.2 渲染产品列表数据
data() {return {productList: [],priceOrder: null, // 'asc' 或 'desc'minPrice: 0,maxPrice: 9999}
},
async onLoad() {await this.loadProducts();
},
methods: {async loadProducts() {const res = await uni.request({url: 'https://api.lukeguazi.com/product/list',data: {minPrice: this.minPrice,maxPrice: this.maxPrice,orderBy: this.priceOrder // 'asc' / 'desc'}});const [err, resp] = res;if (!err && resp.data.code === 200) {this.productList = resp.data.data;}}
}
5.3 价格排序功能
sortByPrice() {if (this.priceOrder === 'asc') {this.priceOrder = 'desc';} else {this.priceOrder = 'asc';}this.loadProducts(); // 重新请求
}
5.4 价格范围筛选(使用 uni.showModal 或自定义弹窗)
openPriceRange() {uni.showModal({title: '设置价格区间',content: '请输入最低价和最高价',editable: true,placeholderText: '如:10,100',success: (res) => {if (res.confirm && res.content) {const [min, max] = res.content.split(',').map(Number);if (!isNaN(min) && !isNaN(max) && min >= 0 && max > min) {this.minPrice = min;this.maxPrice = max;this.loadProducts();} else {uni.showToast({ title: '格式错误', icon: 'none' });}}}});
}
更优方案:使用
uni-popup+ 输入框组件(需安装uni-ui)。
六、产品详情页开发
6.1 路由传参
列表页跳转:
goDetail(id) {uni.navigateTo({url: `/pages/product/detail?id=${id}`});
}
详情页接收参数:
onLoad(options) {const { id } = options;this.loadProductDetail(id);
},
methods: {async loadProductDetail(id) {const res = await uni.request({url: `https://api.lukeguazi.com/product/detail/${id}`});const [err, resp] = res;if (!err && resp.data.code === 200) {this.product = resp.data.data;}}
}
6.2 展示商品详情(含轮播图、描述、购买按钮)
<template><view class="detail-container"><swiper indicator-dots autoplay style="height: 600rpx;"><swiper-item v-for="img in product.images" :key="img"><image :src="img" mode="aspectFill" style="width:100%;height:100%"></image></swiper-item></swiper><view class="info"><text class="title">{{ product.name }}</text><text class="price">¥{{ product.price }}</text><button @click="addToCart" class="buy-btn">加入购物车</button></view></view>
</template>
七、App 打包(原生 App)
7.1 配置 manifest.json
- 打开
manifest.json - 基础配置:
- App名称:鲁嗑瓜子
- App图标:上传 1024x1024 PNG
- 启动页:可选
- 模块权限:勾选“网络”、“存储”等
- SDK 配置:如需推送、支付,按需勾选
7.2 云打包步骤(HBuilderX)
- 菜单栏:
发行→原生App-云打包 - 选择平台:Android / iOS
- Android:
- 包名:
com.lukeguazi.app - 证书:使用公用测试证书(或自定义)
- 包名:
- 点击“打包”
- 等待 5-10 分钟,下载 APK
注意:iOS 打包需 Apple 开发者账号和证书。
八、H5 发布
8.1 本地构建 H5
- 菜单:
发行→网站-H5手机版 - 选择发布目录(如
dist/build/h5) - 构建完成后,将整个
h5文件夹部署到服务器(如 Nginx、Apache)
8.2 配置 H5 路由(history 模式)
在 manifest.json 中:
"h5": {"router": {"mode": "history","base": "/lukeguazi/"}
}
部署时需配置服务器支持 history fallback(如 Nginx 的 try_files)。
九、App 发布(上架)
9.1 Android(应用市场)
- 准备材料:
- APK 文件
- 应用介绍、截图(5 张)
- 隐私政策 URL(必须)
- 上传至:
- 华为应用市场
- 小米应用商店
- 腾讯应用宝
- OPPO/vivo 商店
9.2 iOS(App Store)
- 使用 Apple 开发者账号
- 在 App Store Connect 创建 App
- 使用 Xcode 或 HBuilderX 云打包生成
.ipa - 通过 Transporter 上传
- 提交审核(需提供隐私说明、测试账号等)
十、补充:全局请求封装(推荐)
创建 utils/request.js:
const BASE_URL = 'https://api.lukeguazi.com';export function request(url, options = {}) {uni.showLoading({ title: '加载中' });return new Promise((resolve, reject) => {uni.request({url: BASE_URL + url,method: options.method || 'GET',data: options.data || {},header: {'Content-Type': 'application/json',...options.header},success: (res) => {if (res.statusCode === 200 && res.data.code === 200) {resolve(res.data.data);} else {uni.showToast({ title: res.data.msg || '请求失败', icon: 'none' });reject(res);}},fail: (err) => {uni.showToast({ title: '网络错误', icon: 'none' });reject(err);},complete: () => {uni.hideLoading();}});});
}
使用示例:
import { request } from '@/utils/request';async loadBanner() {try {this.bannerList = await request('/banner/list');} catch (e) {console.error(e);}
}
总结
本项目覆盖了 uni-app 企业级开发的核心流程:
- 页面布局(Flex + rpx)
- 网络请求(封装 + 错误处理)
- 动态渲染(v-for)
- 交互功能(排序、筛选)
- 多端发布(H5 + App)
所有代码均已在 HBuilderX 中验证可用,可直接用于实战项目。
