小程序项目——黑马优购
1. 起步
- 1)uni-app框架:本项目用的是uni-app框架进行开发的,因为uni-app框架是使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到 iOS、Android、H5、以及各种小程序、快应用等多个平台。
- 2)开发工具:用HBuilderX 来开发,因为uni-app项目都是用HbuildX来开发HBuilderX官网
- 3)sass编译:为了方便编写scss/sass样式,建议安装 scss/sass 编译插件下载地址;进入之后点击——使用 HBuilderX 导入插件,登入HBuilderX,进行下载
- 4)新建项目:
- ① 文件 ==》 新建 ==》 项目
- ② 填写项目的一些基本的信息

- 5)uni-app项目目录结构

- 6)项目运行到微信开发者工具
- ① 填写自己的微信小程序的 AppID:manifest.json文件中 ==》 选择微信小程序配置 ==》 再填写微信小程序ID
- ② 在 HBuilderX 中,配置“微信开发者工具”的安装路径:工具 ==》 设置 ==》 运行设置 ==》 再填写微信开发者工具的存放路径
- ③ 开启微信开发者者工具的“服务端口”:设置 ==》 安全 ==》 服务端口开启
- ④ Hbuildx中:运行 ==》 运行到小程序模拟器 ==》 微信开发者工具;
- 作用:将当前项目运行到微信开发者工具中,是为了方便查看项目的效果,代码编辑还是在HBuilderX中
- 7)使用git管理项目
① 项目根目录中创建
.gitignore忽略文件:用来忽略一些不需要版本管理的文件
② unpackage目录下创建
.gitkeep文件进行占位:因为忽略掉了unpackage里的唯一一个文件dist,unpackage也不会被git追踪,所以③ 初始化本地仓库:
git init / git add . / git commit -m '初始化项目'④ 创建远程仓库,把本地仓库和远程仓库进行关联
2. tabBar页面

- 1)创建tabBar分支:
git checkout -b tabBar - 2)创建tabBar页面:
- ① 在pages右键新建页面 ⇒ 依次创建home、cate、cart、my页面
- ② 新建每个页面时有如下配置:css样式用的是scss

- 3)页面新建成功:pages.json文件中 ⇒ pages节点中生成每个tabBar页面的页面路径
- 4)配置tabBar效果:pages.json文件 ⇒ 配置tabBar节点。代码和在微信开发者工具中的配置是一样的
"tabBar": {
"selectedColor": "#C00000", // 选中tab栏文本颜色
"list": [
{
"pagePath": "pages/home/home",
"text": "首页",
"iconPath": "static/tab_icons/home.png",
"selectedIconPath": "static/tab_icons/home-active.png"
},
{
"pagePath": "pages/cate/cate",
"text": "分类",
"iconPath": "static/tab_icons/cate.png",
"selectedIconPath": "static/tab_icons/cate-active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "static/tab_icons/cart.png",
"selectedIconPath": "static/tab_icons/cart-active.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/tab_icons/my.png",
"selectedIconPath": "static/tab_icons/my-active.png"
}
]
}
- 4)删除默认的index首页:HBuilderx(pages.json中路径代码和pages中的文件夹)和微信开发者工具中的index首页
- 5)修改导航条样式效果:pages.json文件 ⇒
globalStyle节点(和tabBar同级)
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "黑马优购",
"navigationBarBackgroundColor": "#C00000",
"backgroundColor": "#FFFFFF"
}
- 6)分支的提交与合并
- ① 进行本地commit提交:
git add . / git commit -m "完成了 tabBar 的开发" - ② 提交到远程仓库进行保存:
git push -u origin tabBar - ③ 将tabBar代码合并到主分支:
git checkout master / git merge tabBar
- ① 进行本地commit提交:
3. 首页
- 首页的代码全部定义在:pages/home/home.vue中
- 结构定义在template标签中,逻辑定义在script标签中,样式定义在
3.1 创建home分支
- 首先创建home分支
git checkout home
3.2 配置网络请求
- 1)传统弊端:axios——小程序不能使用;wx.request()—— 功能太简单,不支持拦截器。
- 2) 因此:使用@escook/request-miniprogram第三方包,下载使用参考官方文档
- 3)main.js中进行配置
// 1. 按需导入$http
import { $http } from '@escook/request-miniprogram'
// 2. uni对象上挂载$http(以后就使用uni.$http)
uni.$http = $http
// 3. 配置本项目中的请求的根路径
$http.baseUrl = 'https://www.uinav.com'
// 4. 请求拦截器上加上loading效果
$http.beforeRequest = function (options) {
uni.showLoading({
title: '数据加载中...',
})
}
// 5. 响应拦截器上隐藏loading效果
// 请求完成之后做一些事情
$http.afterRequest = function () {
uni.hideLoading()
}
3.3 轮播图区域

3.3.1 获取轮播图的数据
- 1)data中:定义存放轮播图的数组
- 2)onLoad生命周期函数中:调用方法
- 3)methods中:定义获取数据的方法
- ① 用uni.$http.get 来获取数据
- ② 用async和await来获取数据,代表值是一个promise对象
- ③ 判断状态码是否等于200,如果不是的话,调用
uni.showToast提示他 - ④ 为data中数据赋值
export default {
data() {
return {
// 1. 轮播图的数据列表,默认为空数组
swiperList: [],
}
},
onLoad() {
// 2. 在小程序页面刚加载的时候,调用获取轮播图数据的方法
this.getSwiperList()
},
methods: {
// 3. 获取轮播图数据的方法
async getSwiperList() {
// 3.1 发起请求
const { data: res } = await uni.$http.get('/api/public/v1/home/swiperdata')
// 3.2 请求失败
if (res.meta.status !== 200) {
return uni.showToast({
title: '数据请求失败!',
duration: 1500,
icon: 'none',
})
}
// 3.3 请求成功,为 data 中的数据赋值
this.swiperList = res.message
},
},
}
3.3.2 渲染轮播图的UI结构
- 1)swiper组件:轮播图还是用swiper组件(微信小程序开发工具的用法)
- 2)v-for循环:循环渲染用Vue的v-for循环,:key用来做唯一标识
- 3)属性动态绑定:src:图片的路径属性用动态绑定(Vue)
- 4)css配置:最后美化一下UI结构
<!-- 轮播图区域 -->
<swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000" :circular="true">
<!-- 循环渲染轮播图的 item 项 -->
<swiper-item v-for="(item, i) in swiperList" :key="i">
<view class="swiper-item">
<!-- 动态绑定图片的 src 属性 -->
<image :src="item.image_src"></image>
</view>
</swiper-item>
</swiper>
swiper {
height: 330rpx;
.swiper-item,
image {
width: 100%;
height: 100%;
}
}
3.3.3 配置小程序分包
- 1)原因:我们把tabBar页面放到主包中,把其他页面放到分包中,减少小程序启动的加载时间
- 2)配置步骤:项目根目录创建
subpkg文件夹》 pages.json中配置subPackages 节点(和pages同级,用来配置分包结构)==》 在subpkg文件夹上新建页面 ==》 分包处:选择subpkg分包
"subPackages": [
{
"root": "subpkg",
"pages": []
}
]

3.3.4 点击轮播图跳转到详情页面
- 1)把包裹图片的view组件 ,改成navigator组件
- 2)动态绑定url属性进行跳转
<!--动态拼接上参数-->
<navigator class="swiper-item" :url="'/subpkg/goods_detail/goods_detail?goods_id=' + item.goods_id">
<!-- 动态绑定图片的 src 属性 -->
<image :src="item.image_src"></image>
</navigator>
3.3.5 封装uni.$showMsg() 方法
- 1)uni.showToast()用来提示信息 ==》 每次数据请求的时候都要调用 ==》 因此直接封装一个方法
- 2)在main.js中封装uni.s h o w M s g ( ) , 之 后 再 每 次 调 用 的 时 候 直 接 调 用 ‘ u n i . showMsg() ,之后再每次调用的时候直接调用`uni.showMsg(),之后再每次调用的时候直接调用‘uni.showMsg`就好
- 3)uni.$showMsg:title和duration有默认的值,也可以传递数据
uni.$showMsg = function (title = '数据加载失败!', duration = 1500) {
uni.showToast({
title,
duration,
icon: 'none'
})
}
3.4 分类导航区域

3.4.1 获取分类导航区域的数据
- 1)data中:定义收集分类导航的数据
- 2)onLoad中:调用获取分类导航数据的方法
- 3)methods中:定义获取分类导航数据的方法
- ① 获取数据:uni.$http.get获取;async和await获取promise对象的数据;数据解构赋值
- ② 响应状态码:如果不等于200,就return出去,并且调用uni.$showMsg()提示获取失败
- ③ 给数据赋值
export default {
data() {
return {
// 1. 分类导航的数据列表
navList: [],
}
},
onLoad() {
// 2. 在 onLoad 中调用获取数据的方法
this.getNavList()
},
methods: {
// 3. 在 methods 中定义获取数据的方法
async getNavList() {
const { data: res } = await uni.$http.get('/api/public/v1/home/catitems')
if (res.meta.status !== 200) return uni.$showMsg()
this.navList = res.message
},
},
}
3.4.2 渲染分类导航区域的UI结构
- 1)v-for循环渲染数据:还要加:key=“i”,唯一性;每一项图片用view组件包裹
- 2)图片css样式:图片设定宽高 + 父级盒子设定(display:flex)让他同一行显示
<view class="nav-list">
<view class="nav-item" v-for="(item, i) in navList" :key="i">
<image :src="item.image_src" class="nav-img"></image>
</view>
</view>
/* scss样式可以用包裹 */
.nav-list {
display: flex;
/* 均分区域 */
justify-content: space-around;
margin: 15px 0;
.nav-img {
width: 128rpx;
height: 140rpx;
}
}
3.4.3 点击分类图标跳转到分类页面
- 1)给图片每一项绑定事件处理函数
- 2)在methods中定义事件处理函数
<view class="nav-item" @click="navClickHandler(item)">
<image :src="item.image_src" class="nav-img"></image>
</view>
methods: {
navClickHandler(item) {
// 首先判断它是不是分类那一项,判断他的名字是不是叫分类
if (item.name === '分类') {
// 如果是的哈进行跳转
uni.switchTab({
url: '/pages/cate/cate'
})
}
}
}
3.5 楼层区域

3.5.1 获取楼层数据
- 1)data中:定义收集分类导航的数据
- 2)onLoad中:调用获取分类导航数据的方法
- 3)methods中:定义获取分类导航数据的方法
- ① 获取数据:uni.$http.get获取;async和await获取promise对象的数据;数据解构赋值
- ② 响应状态码:如果不等于200,就return出去,并且调用uni.$showMsg()提示获取失败
- ③ 给楼层数据赋值
export default {
data() {
return {
// 1. 楼层的数据列表
floorList: [],
}
},
onLoad() {
// 2. 在 onLoad 中调用获取楼层数据的方法
this.getFloorList()
},
methods: {
// 3. 定义获取楼层列表数据的方法
async getFloorList() {
const { data: res } = await uni.$http.get('/api/public/v1/home/floordata')
if (res.meta.status !== 200) return uni.$showMsg()
this.floorList = res.message
},
},
}
3.5.2 渲染楼层的标题
- 1)楼层的标题:其实也是一张图片,所以我们要做的就是把图片渲染出来
- 2)在楼层的每一项里面:用v-for进行循环渲染楼层数据
- 3)楼层标题:动态绑定数据的floor_title中的图片地址
<!-- 楼层区域 -->
<view class="floor-list">
<!-- 楼层 item 项 -->
<view class="floor-item" v-for="(item, i) in floorList" :key="i">
<!-- 楼层标题 -->
<image :src="item.floor_title.image_src" class="floor-title"></image>
</view>
</view>
.floor-title {
height: 60rpx;
width: 100%;
}
3.5.3 渲染楼层里面的图片

- 1)图片布局:左边一个大盒子(放一张图片)+ 右边一个盒子(放四张图片)
- 2)UI结构:我们先把图片数据给渲染出来
- ① 结构:图片区域一个盒子包裹 + 左侧图片一个盒子包裹 (里面放image组件)+ 右侧图片盒子包裹(图片每一项再用盒子包裹,里面放image组件)
- ② 左侧图片:图片路径绑定数组项中的product_list中的第一项;宽度也是动态绑定,因为返回值中有宽度;mode设置为widthFix(表示高度适应宽度)
- ③ 右侧图片:要接着循环遍历一次item.product_list;并且不能显示第一张图片,因此用v-if条件渲染;宽度和mode和第一张图片一样的
<!-- 楼层图片区域 -->
<view class="floor-img-box">
<!-- 左侧大图片的盒子 -->
<view class="left-img-box">
<image :src="item.product_list[0].image_src" :style="{width: item.product_list[0].image_width + 'rpx'}" mode="widthFix"></image>
</view>
<!-- 右侧 4 个小图片的盒子 -->
<view class="right-img-box">
<view class="right-img-item" v-for="(item2, i2) in item.product_list" :key="i2" v-if="i2 !== 0">
<image :src="item2.image_src" mode="widthFix" :style="{width: item2.image_width + 'rpx'}"></image>
</view>
</view>
</view>
- 3)css样式
- ① 右侧图片盒子:flex布局 + 允许元素换行(flex-wrap: wrap)+ 每一项平分空间
- ② 图片大盒子:flex布局
.right-img-box {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.floor-img-box {
display: flex;
padding-left: 10rpx;
}
3.5.4 点击图片跳转到商品列表页
- 1)新建页面:在subpkg文件夹上右键 ==》 新建商品列表页面

- 2)处理url地址:后台会返回一个要跳转的url地址,但是他的地址,跟我们要跳转的地址不一样
- ① 后台url地址:/pages/goods_list?携带的参数
- ② 跳转的地址:/subpkg/goods_list/goods_list?携带的参数
- ③ 因此我们要给返回值自定义一个属性url:值为——路径+返回的url参数
- 定义url:图片路径所在的数组,给每一项循环遍历加上自定义属性url
- url:页面路径 + 参数(返回的数据根据 ——?,进行切割之后的第一项)
// 通过双层 forEach 循环,处理 URL 地址
res.message.forEach(floor => {
floor.product_list.forEach(prod => {
prod.url = '/subpkg/goods_list/goods_list?' + prod.navigator_url.split('?')[1]
})
})
// 2. 再把值给楼层数据
this.floorList = res.message
- 3)把包裹图片的盒子改成——navigator组件,动态绑定url属性进行跳转
<!-- 楼层图片区域 -->
<view class="floor-img-box">
<!-- 左侧大图片的盒子 -->
<navigator class="left-img-box" :url="item.product_list[0].url">
<image :src="item.product_list[0].image_src" :style="{width: item.product_list[0].image_width + 'rpx'}" mode="widthFix"></image>
</navigator>
<!-- 右侧 4 个小图片的盒子 -->
<view class="right-img-box">
<navigator class="right-img-item" v-for="(item2, i2) in item.product_list" :key="i2" v-if="i2 !== 0" :url="item2.url">
<image :src="item2.image_src" mode="widthFix" :style="{width: item2.image_width + 'rpx'}"></image>
</navigator>
</view>
</view>
3.6 home分支提交
- 1)home分支本地的commit提交
// 将本地代码提交到暂存区
git add .
// 将暂存区代码提交到仓库
git commit -m "完成了 home 首页的开发"
- 2)将本地分支提交到远程仓库
git push -u origin home
- 3 )将home分支合并到主分支
git checkout master
git merge home
- 4)删除本地的 home 分支
git branch -d home
- 通过ctrl + E可以选中所有相似的代码,方便多选加class类名

版权声明:本文为weixin_46025916原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。