3.0 创建 home 分支
运行如下的命令,基于 master 分支在本地创建 home 子分支,用来开发和 home 首页相关的功能:
git checkout -b home
#3.1 配置网络请求
由于平台的限制,小程序项目中不支持 axios,而且原生的 wx.request()
API 功能较为简单,不支持拦截器等全局定制的功能。因此,建议在 uni-app 项目中使用 @escook/request-miniprogram
第三方包发起网络数据请求。
请参考 @escook/request-miniprogram 的官方文档进行安装、配置、使用
官方文档:https://www.npmjs.com/package/@escook/request-miniprogram
1 安装
npm install @escook/request-miniprogram
2最终,在项目的 main.js
入口文件中,通过如下的方式进行配置:
import { $http } from '@escook/request-miniprogram'
uni.$http = $http // 挂载到顶级上
// 配置请求根路径
$http.baseUrl = 'https://www.uinav.com'
// 请求开始之前做一些事情
$http.beforeRequest = function (options) {
uni.showLoading({
title: '数据加载中...',
})
}
// 请求完成之后做一些事情
$http.afterRequest = function () {
uni.hideLoading()
}
#3.2 轮播图区域
#3.2.1 请求轮播图的数据
实现步骤:
-
在 data 中定义轮播图的数组
-
在 onLoad 生命周期函数中调用获取轮播图数据的方法
-
在 methods 中定义获取轮播图数据的方法
示例代码:
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.2.2 渲染轮播图的 UI 结构
-
渲染 UI 结构:
<template>
<view>
<!-- 轮播图区域 -->
<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>
</view>
</template>
indicator-dots 是否显示面板指示点
autoplay 是否自动切换
interval 自动切换时间
duration 滑动动画时长
circular 是否采用衔接滑动,即播放到末尾后重新回到开头
-
美化 UI 结构:
<style lang="scss"> swiper { height: 330rpx; .swiper-item, image { width: 100%; height: 100%; } } </style>
报错:uniapp编译报错页面空白,控制台报错 “ TypeError: Cannot read property ‘call‘ of undefined”
刚开始创建项目时并没有出现这个问题,但是当我写了一些页面后突然之间就报了这个问题,于是查阅了一些文章找到了我这种出现的原因,因此记录下,供大家借鉴。
报错的主要原因就是主包太大,尽管我分包了但是一些图片这些也是算在主包里面的,因此建议大家图片尽量放在数据库中,再加上uniapp在运行的时候没有打开文件压缩所以就这样了。
报错2: 微信小程序TypeError: Cannot read property ‘$$‘ of undefined
<!-- 轮播图 -->
<view style="height: {{height}}rpx;">
<swiper wx:if="{{list.imageurl.length>0}}" indicator-dots="{{true}}" current="currentTab" bindchange="switchTab" indicator-color="#2E8B57" circular="true" style="height:100%;">
<block wx:for="{{list.imageurl}}" wx:key="index" >
<swiper-item bindtap='{{item.caozuoname}}' style="justify-content: center;display: flex;align-items: center;">
<image src='{{item}}' bindtap="fangda" mode="aspectFit" style="border-radius: 5rpx;display: block;height: 1000rpx;;" />
</swiper-item>
</block>
</swiper>
</view>
解决方法就是用wx:if判断swiper是否需要渲染
如果里面是一个图片,但是src为null,就会报错,需要用wx:if判断,不能渲染没有src的图片
<swiper wx:if="{{list.imageurl.length>0}}" 这里
uniapp判断使用v-if
uni-app之条件判断详解【uni-app小程序开发】(二)_uniapp if_上进小菜猪的博客-CSDN博客
报错3: Unexpected token语法错误
用VScode打开代码排查就行,HBuilderX有点小毛病,有时候错误定位不知道的定到哪里去了
报错4:uni-app运行微信小程序时文件查找失败的问题
此类问题主要是文件的路径不正确导致的。
造成这种问题的一个比较坑的原因,就是HBuilderX在新建目录的时候会在pages.json中添加路径,如果你修改了路径,pages.json并不会自动更改这个路径,导致无法找到新的路径地址。所以解决这个问题也非常简单,就是在pages.json文件里,替换掉之前的错误路径即可。
注:这类问题运行在原生手机或者模拟器时是没有问题的,但是在微信小程序里无法运行。
注意: 删除文件的时候,记得吧page.json配置删除了!!!
=====
#3.2.3 配置小程序分包
分包可以减少小程序首次启动时的加载时间
为此,我们在项目中,把 tabBar 相关的 4 个页面放到主包中,其它页面(例如:商品详情页、商品列表页)放到分包中。在 uni-app 项目中,配置分包的步骤如下:
-
在项目根目录中,创建分包的根目录,命名为
subpkg(不要写错,否则配置文件不会自动生成配置)
-
在
pages.json
中,和pages
节点平级的位置声明subPackages
节点,用来定义分包相关的结构:{ "pages": [ { "path": "pages/home/home", "style": {} }, { "path": "pages/cate/cate", "style": {} }, { "path": "pages/cart/cart", "style": {} }, { "path": "pages/my/my", "style": {} } ], "subPackages": [ { "root": "subpkg", "pages": [] } ] }
-
在
subpkg
目录上鼠标右键,点击新建页面
选项,并填写页面的相关信息:
自动将路径记录到了配置文件当中:查看
#3.2.4 点击轮播图跳转到商品详情页面
将 <swiper-item></swiper-item>
节点内的 view
组件,改造为 navigator
导航组件,并动态绑定 url 属性
的值。
-
改造之前的 UI 结构:
<swiper-item v-for="(item, i) in swiperList" :key="i"> <view class="swiper-item"> <!-- 动态绑定图片的 src 属性 --> <image :src="item.image_src"></image> </view> </swiper-item>
-
改造之后的 UI 结构:
<swiper-item v-for="(item, i) in swiperList" :key="i"> <navigator class="swiper-item" :url="'/subpkg/goods_detail/goods_detail?goods_id=' + item.goods_id"> <!-- 动态绑定图片的 src 属性 --> <image :src="item.image_src"></image> </navigator> </swiper-item>
url 是基本路径+ id
uniapp路由跳转的六种方式_uniapp跳转方式_天使的同类的博客-CSDN博客
【uniapp小程序】路由跳转navigator传参封装_uniapp路由跳转传参_不苒的博客-CSDN博客
测试: 单击 跳转到了详情页
如果没有跳转过去, url 路径是否正确 : 是否添加
#3.2.5 封装 uni.$showMsg() 方法
当数据请求失败之后,经常需要调用 uni.showToast({ /* 配置对象 */ })
方法来提示用户。此时,可以在全局封装一个 uni.$showMsg()
方法,来简化 uni.showToast()
方法的调用。具体的改造步骤如下:
-
在
main.js
中,为uni
对象挂载自定义的$showMsg()
方法:// 封装的展示消息提示的方法 uni.$showMsg = function (title = '数据加载失败!', duration = 1500) { uni.showToast({ title, duration, icon: 'none', }) }
-
今后,在需要提示消息的时候,直接调用
uni.$showMsg()
方法即可:async getSwiperList() { const { data: res } = await uni.$http.get('/api/public/v1/home/swiperdata') if (res.meta.status !== 200) return uni.$showMsg() this.swiperList = res.message }
默认参数是 数据请求失败
#3.3 分类导航区域
#3.3.1 获取分类导航的数据
实现思路:
-
定义 data 数据
-
在 onLoad 中调用获取数据的方法
-
在 methods 中定义获取数据的方法
示例代码如下:
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.3.2 渲染分类导航的 UI 结构
进行分栏展示
1 定义如下的 UI 结构:
<!-- 分类导航区域 -->
<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>
图片在uni是 image 不是img
2 通过如下的样式美化页面结构:
.nav-list {
display: flex;
justify-content: space-around;
margin: 15px 0;
.nav-img {
width: 128rpx;
height: 140rpx;
}
}
#3.3.2 点击第一项,切换到分类页面
-
为
nav-item
绑定点击事件处理函数:<!-- 分类导航区域 --> <view class="nav-list"> <view class="nav-item" v-for="(item, i) in navList" :key="i" @click="navClickHandler(item)"> <image :src="item.image_src" class="nav-img"></image> </view> </view>
-
定义
navClickHandler
事件处理函数:// nav-item 项被点击时候的事件处理函数 navClickHandler(item) { // 判断点击的是哪个 nav if (item.name === '分类') { uni.switchTab({ url: '/pages/cate/cate' }) } }
因为切换到tabBar页面,只能通过uni.switchTab 进行跳转
#3.4 楼层区域
#3.4.1 获取楼层数据
实现思路:
-
定义 data 数据
-
在 onLoad 中调用获取数据的方法
-
在 methods 中定义获取数据的方法
示例代码如下:
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.4.2 渲染楼层的标题
-
定义如下的 UI 结构:
<!-- 楼层区域 --> <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%; display: flex; }
#3.4.3 渲染楼层里的图片
-
定义楼层图片区域的 UI 结构:
宽度需要动态的绑定:
指定宽度,高度自适应,添加mode="widthFix"
<!-- 楼层图片区域 -->
<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>
-
美化楼层图片区域的样式:
.right-img-box { display: flex; flex-wrap: wrap; justify-content: space-around; } .floor-img-box { flex:1 display: flex; padding-left: 10rpx; }
不加flex:1 右边都是乱的,对齐不了。
#3.4.4 点击楼层图片跳转到商品列表页
-
在
subpkg
分包中,新建goods_list
页面
-
楼层数据请求成功之后,通过双层
forEach
循环,处理 URL 地址:
// 获取楼层列表数据
async getFloorList() {
const { data: res } = await uni.$http.get('/api/public/v1/home/floordata')
if (res.meta.status !== 200) return uni.$showMsg()
// 通过双层 forEach 循环,处理 URL 地址
res.message.forEach(floor => {
floor.product_list.forEach(prod => {
prod.url = '/subpkg/goods_list/goods_list?' + prod.navigator_url.split('?')[1]
})
})
this.floorList = res.message
}
2 把图片外层的 view
组件,改造为 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.5 分支的合并与提交
-
将本地的 home 分支进行本地的 commit 提交:
git add . git commit -m "完成了 home 首页的开发"
-
将本地的 home 分支推送到远程仓库进行保存:
git push -u origin home
-
将本地的 home 分支合并到本地的 master 分支:
git checkout master git merge home
-
删除本地的 home 分支:
git branch -d home