微信小程序开发 外部链接别人的总结查看(超详细保姆式教程)
基础语法
1.数据绑定
1.1 初始化数据
- 页面.js的data选项中
Page({ data: { motto: 'Hello World', id:18 } })
- 使用数据
-
单项数据流:Mustache 语法
a)模板结构中使用双大括号 {{data}}<text id="{{id}}">{{motto}}</text> <input type="text" value="{{motto}}"/>
-
双向数据绑定
-
a)表单项使用 model:value = ‘{{data}}’
<input type="text" model:value="{{motto}}"/>
-
b)坑!!!
- i.双向数据绑定数据变量名不能是简单的a, b, c,否则无法实现
- ii.双向数据绑定不能绑定data路径,如: a.b
<input type="text" model:value="{{a}}"/>
1.2 修改数据
this.setData({message: ‘修改之后的数据’}, callback)
- 特点:
- a)同步修改: this.data值被同步修改
- b)异步更新: 异步将setData 函数用于将数据从逻辑层发送到视图层(异步)
- 注意点:
- a)直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
- b)单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
Page({ data: { motto: 'Hello World', a: 'abc' }, onLoad(){ this.setData({ motto: 'change data' }) } })
2.事件绑定
2.1 事件分类
-
- 冒泡事件
- a) 定义:冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- b) 冒泡事件列表:冒泡官网地址
-
2)非冒泡事件
- a) 定义:当一个组件上的事件被触发后,该事件不会向父节点传递。
- b) 非冒泡事件:表单事件和自定义事件通常是非冒泡事件
非冒泡事件官网地址
2.2 绑定事件
-
bind绑定:事件绑定不会阻止冒泡事件向上冒泡
<view bindtap="handleTap" class='start_container'> <text class='start'>开启小程序之旅</text> </view>
-
catch 绑定: 事件绑定可以阻止冒泡事件向上冒泡
<view catchtap="handleTap" class='start_container'> <text class='start'>开启小程序之旅</text> </view>
2.3 向事件对象传参
- 语法: data-key=value
<button catchtap="changeName" data-name='{{firstName}}'>点击修改名称</button>
-
获取:
event.target.dataset.key || event.currentTarget.dataset.key
-
Event.target 和 event.currentTarget的区别
a.) Event.target是触发事件的对象,但不一样是绑定事件的对象,如: 事件委托,冒泡
b) currentTarget触发事件的对象一定是绑定事件的对象, 没有事件委托
3.列表渲染
3.1 语法说明
wx:for="{{arr}}"
wx:key="唯一值或者index"
<view wx:for="{{ list }}" wx:key="id">
<view>{{ index }} -- {{ item.content }}</view>
</view>
3.2 wx:key
-
同Vue一样,循环遍历的时候需要为每一个item添加唯一的key值
-
Key值分类:
a)Item本身就是唯一值,如: number,string
b)*this,代表item本身,同样需要item自身是唯一的,如;number,string
c)Item的唯一属性,如: id; 官网没有明确语法说明,只能在示例代码中找到 -
注意事项:
a)Wx:key后跟的变量不需要使用插值语法,即不需要使用大括号包裹
b)Item中如果有唯一值属性,可以直接使用
如:item = {id: 1}, 则wx:key = 'id'
3.3 重新命名
1.默认的个体: item
2.默认的下标: index
3.自定义个体变量名称: wx:for-item=’myItem’
4.自定义下标变量名称: wx:for-index=’myIndex’
<view wx:for="{{ list }}" wx:key="id" wx:for-item="myItem" wx:for-index="myIndex">
<view>{{ myIndex}} -- {{myItem.content}}</view>
</view>
4. 条件渲染
4.1 语法说明
wx:if=’条件’
wx:elif=’条件’
wx:else
<view> <!-- 条件渲染 --> <view wx:if="{{ isShow }}">表白成功</view> <view wx:else>表白失败</view> <!-- <view wx:else="{{ !isShow }}">表白失败</view> --> <view>-----------------</view> <view wx:if="{{ sex === 0 }}">男</view> <view wx:elif="{{ sex === 1 }}">女</view> <view wx:else>未知</view> </view>
4.2 wx:if VS hidden 区别
1.hidden用法: <view hidden='{{true}}' ></view>
2.wx:if 等同于 v-if, 条件为false的时候不加载,条件切换的时候决定元素销毁或者重新加载渲染
3.hidden 等同于 v-show, 始终加载元素, 条件切换的时候决定元素的显示和隐藏
5. 模板使用
5.1 定义模板
5.2 引入模板
- 引入模板结构:
- 引入模板样式: @Import ‘模板样式路径’
5.3 使用模板
5.4 向模板导入数据并使用数据
6.生命周期
官方图示:官方图
生命周期函数 | 执行时机 | 执行次数 | 特点说明 |
---|---|---|---|
onLoad | 页面加载时触发 | 1 | 可以通过参数获取打开当前页面路径中的参数 |
onShow | 页面显示/切入前台时触发 | 多次 | 如页面没有被销毁,会重复多次显示隐藏,可以在此发送请求获取最新数据 |
onReady | 页面初始化渲染完成时触发 | 1 | 可以同UI界面进行交互 |
onHide | 页面隐藏/切入后台时触发 | 多次 | wx.navigateTo 或底部 tab 切换到其他页面,小程序切入后台等 |
onUnload | 页面卸载时触发 | 1 | wx.redirectTo或wx.navigateBack到其他页面时 |
个人见解
官网生命周期图示是错误的;错误部分:标注onLoad及onShow执行的位置不对
参考:小程序启动执行的所有流程
参考地址:
https://developers.weixin.qq.com/miniprogram/dev/framework/performance/tips/start_process.html
7.小程序适配方案: rpx (responsive pixel响应式像素单位)
小程序适配单位: rpx
规定任何屏幕下宽度为750rpx
小程序会根据屏幕的宽度不同自动计算rpx值的大小
Iphone6下: 1rpx = 1物理像素 = 0.5px
8. 小程序API
8.1 API使用说明
- 小程序提供了很多实用的方法供开发者使用
- 小程序全局对象是: wx
- 所有的API都保存在wx对象中
8.2 常用API
- 界面交互
a)显示消息提示框: wx.showToast()
b)显示消息加载框: wx.showLoading()
c)关闭消息提示框: wx.hideToast()
d)关闭消息加载框: wx.hideLoading()
e)提示消息警告框:wx.showModal() - 路由跳转
a)wx.navigateTo() 保留当前页面,跳转到应用内的某个页面
b)wx.redirectTo() 关闭当前页面,跳转到应用内的某个页面
c)wx.switchTab() 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 - 网络请求
a)wx.request() - 本地存储
a)wx.setStorage() 异步设置
b)wx.setStorageSync() 同步设置
c)wx.getStorage() 异步获取
d)wx.getStorageSync() 同步获取 - 媒体
a)wx.getBackgroundAudioManager() 获取全局唯一的背景音频管理器
b)wx.playVoice()
6.支付
a)Wx.requestPayment()
8.3 快速查找技巧
- 小程序的初学者可能对于小程序的官网的众多内容一时毫无头绪,无从下手不知道从哪来找想要的内容
- 当在小程序中想要实现某一种布局,查看:组件
- 当在小程序中想要实现某一个功能,查看: API
- 当在小程序中想要进行某一个配置或者某一种页面语法,查看: 框架 + 指南
- 查看小程序官网的时候要细心,最好是将要使用的API的相关内容看完整,因为API的配置及限制较多
9.组件传参
组件传参 - 把标题"猜你喜欢", "人气推荐"传入到组件中
怎么传? — 标签直接帮属性即可
<goods-list title="猜你喜欢" list="{{likeList}}"></goods-list>
怎么接?
组件内使用 properties 接(不支持数组,支持对象和配置对象)
// 不支持数组写法
// properties: ["title"],
// 支持对象写法
// properties: {
// title: String,
// },
// 支持配置对象写法
properties: {
title: {
type: String,
required: true
},
list: {
type: Array,
required: true
}
},
路由传参query
使用标签和js都可以跳转
-
标签跳转
<navigator url="/pages/goods/list/list?category2Id={{item.id}}" ></navigator>
同时携带了 query 参数(路由带参)
-
js跳转
wx.navigateTo({ url: '/pages/goods/list/list', });
没带参数
跳转页面的API
wx.switchTab 跳转到tabbar页面
wx.redirectTo 关闭当前页面,跳转下一个页面,当前页面不在历史记录中
wx.navigateTo 跳转页面(有历史记录)
wx.navigateBack({ delta: 1 }) 回退页面,没有参数默认是1
wx.reLaunch 关闭所有的页面,打开到应用内的某个页面
进阶知识
1. 小程序本地存储
1.1 语法说明
-
存入数据
a)wx.setStorage() 异步
b)wx.setStorageSync() 同步
-
读取数据
a)wx.getStorage()异步
b)wx.getStorageSync() 同步
-
删除数据
a)wx.removeStorage() 异步
b)wx.removeStroageSync() 同步
-
清空数据
a)wx.clearStorage() 异步
b)wx.clearStorageSync() 同步
1.2 注意事项
- 除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用
- 单个 key 允许存储的最大数据长度为 1MB
- 所有数据存储上限为 10MB
1.3 官网对应地址
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorage.html
2. 小程序前后端交互
2.1 语法说明
- wx.request()
2.2 相关配置
- 每个微信小程序需要事先设置通讯域名,小程序只可以跟指定的域名进行网络通信
- 服务器域名请在 「小程序后台-开发-开发设置-服务器域名」 中进行配置
- 默认超时时间和最大超时时间都是 60s
- 超时时间可以在 app.json 中通过 networktimeout 配置
2.3 注意事项
- 小程序为了安全起见只支持Https请求
- wx.request最大并发限制10个
2.4 官网对应地址
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorage.html
3. 小程序页面通信
3.1 路由传参
- 传参方式
a)路由地址中 + query传参数
b)示例:url?a=123
wx.navigateTo({ url: '/pages/target/target?a=1&b=2', });
- 获取参数
a)跳转目标页面的onLoad函数中的options实参中获取onLoad(options){ const {a, b} = options; }
3.2 消息订阅发布
- 使用第三方库:
pubsub-js
- 安装:
npm install pubsub-js
- 使用:
a)import PubSub from ‘pubsub-js’
b)订阅消息:PubSub.subscribe(‘eventName’, callback)
c)发布消息:PubSub.publish(‘eventName’, data)
d)取消订阅:PubSub.unsubscribe(‘eventName’)
3.3 eventChannel 事件通道
-
订阅事件
a)wx.navigateTo()跳转的时候在events选项中定义事件名及事件对应的回调
-
获取事件总线对象
a)目标页面中通过: 实例.getOpenerEventChannel()
b)示例: const eventChannel = this.getOpenerEventChannel() -
触发事件
a)eventChannel.emit(‘事件名’, data)
3.4 借助app传参
- 获取App
const app = getApp()
- 在app上写入数据
app.currentAddress = currentAddress;
- 获取数据
const app = getApp()
let currentAddress = app.currentAddress
获取数据
4. 小程序自定义组件
4.1. 创建组件
- 开发工具中在指定的文件夹下右键新建组件
a)建议:文件夹名称与组件名称最好一致。 - 组件对应的json文件中设置: component: true
{
"component": true,
"usingComponents": {},
"navigationStyle": "custom" -----> 自定义导航 导航栏样式
"navigationBarTitleText": "登录" -----> 自定义文字
}
4.2. 使用组件
1.使用组件的页面的json文件中注册使用组件
{
"usingComponents": {
"goods-list": "/components/goods-list/goods-list"
}
}
<goods-list title="猜你喜欢" list="{{ likeList }}"></goods-list>
5. 小程序使用npm包
5.1 初始化package.json
npm init
5.2 勾选允许使用npm(老版本)
老版本需要勾选
新版本已全面支持,没有当前选项
5.3 下载npm包
npm install packageName
5.4 构建npm
- 微信开发工具 —> 工具选项 —> 构建npm
- 会将node_modules中的包打包到miniprogram_npm中
a)小程序中使用的第三方包内容会去miniprogram_npm中查找而不是node_modules - 注意:
a)开发中如果使用UI组件库,每次引入新的组件使用可能会导致样式不能生效,需要再次重新构建npm即可
5.5 流程执行不完整带来的错误
6.小程序登录流程
6.1 刚刚被作废的方式
6.1.1 首次获取
- Button组件设置open-type属性为getUserInfo
<button open-type=’getUserInfo’></button>
- 设置后首次登陆点击button可以弹出授权窗口
- 注意: 授权的动作只发生一次,除非清除缓存,点击butotn授权一次之后再点击失效,不会弹出授权窗口
- 官网对应地址
https://developers.weixin.qq.com/miniprogram/dev/component/button.html
6.1.2 授权之后获取
wx.getUserInfo()
- 官网对应地址:
https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserInfo.html
6.1.3 作废说明
a) 依然可以使用,但不会出现授权弹窗
b) 获取到的用户名为 ‘微信用户’, 头像为灰色头像
6.2 目前推荐登录方式
6.2.1 通过token标识用户
- 通过用户临时登录code获取用户唯一标识token
- 如果需要展示用户头像和用户自定义用户名可通过页面引导用户自行设置
6.2.2 登录流程图解
8.6.2.3 登录流程说明
-
wx.login()
code是临时标识,只有5分钟内有效 -
发送code给服务器端
-
服务器端发送请求携带参数(code, appSecret, appId)给微信服务器获取openId
a) 微信接口API: GET https://api.weixin.qq.com/sns/jscode2session -
appSecret,appId在小程序首页获取
-
服务器获取openId后进行加密返回给前端Token标识
7. 小程序使用UI组件库vant
7.1 下载安装
- Npm安装
npm i @vant/weapp -S --production
- Yarn安装
yarn add @vant/weapp –production
7.2 修改app.json
- 操作: 将 app.json 中的 “style”: “v2” 去除
- 原因:程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
7.3 修改project.config.json
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
],
7.4 构建npm
微信开发工具 —> 工具 —> 构建npm
7.5 引入组件
- 页面.json文件中
{
"usingComponents": {
"van-action-sheet": "@vant/weapp/action-sheet/index",
"van-stepper": "@vant/weapp/stepper/index",
"van-icon": "@vant/weapp/icon/index",
"van-button": "@vant/weapp/button/index"
}
}
8.7.6 使用组件
<van-button block type="primary" round bindtap='handleSubmit'>确定</van-button>
8. 小程序分包流程
8.1 为什么要分包
- 小程序要求压缩包体积不能大于2M,否则无法发布
- 实际开发中小程序体积如果大于2M就需要使用分包机制进行发布上传
- 分包后可解决2M限制,并且能分包加载内容,提高性能
- 分包后单个包的体积不能大于2M
- 包后所有包的体积不能大于20M
8.2 分包形式
- 常规分包
- 独立分包
- 分包预下载
- 分包异步化
8.3 常规分包
- 开发者通过在 app.json subpackages 字段声明项目分包结构
- 特点:
- a)加载小程序的时候先加载主包,当需要访问分包的页面时候才加载分包内容
- b)分包的页面可以访问主包的文件,数据,图片等资源
- c)主包:
- i.主包来源: 除了分包以外的内容都会被打包到主包中
- ii.通常放置启动页/tabBar页面
- 注意点:root包名必须是当前分包目录名
8.4 独立分包
- 设置 independent为true
- 特点:
- a)独立分包可单独访问分包的内容,不需要下载主包
- b)独立分包不能依赖主包或者其他包的内容
- 使用场景
- a)通常某些页面和当前小程序的其他页面关联不大的时候可进行独立分包
- b)如:临时加的广告页 || 活动页
8.5 分包预下载
- 配置
- a)app.json中设置preloadRule选项
- b)key(页面路径): {packages: [预下载的包名 || 预下载的包的根路径])}
- 特点:
- a) 在加载当前包的时候可以设置预下载其他的包
- b) 缩短用户等待时间,提高用户体验
8.6 分包异步化
- 理解:
a)独立分包不能依赖其他分包文件,如果要加载使用其他分包怎么办? - 设计思想:
a)等待其他分包加载后,异步加载依赖文件 - 异步分类
-
a)异步加载组件
- i.使用内置组件设置占位
- ii.等待异步加载后再加载使用依赖的组件
- iii.设置选项:对应组件json文件中 ‘componentPlaceholder’ 字段
// subPackageA/pages/index.json { "usingComponents": { "button": "../../commonPackage/components/button", "list": "../../subPackageB/components/full-list", "simple-list": "../components/simple-list" }, "componentPlaceholder": { "button": "view", "list": "simple-list" } }
-
b)异步加载js文件
- require 方法
- 回调函数方式
/* 回调函数形式 */ let findUserAddress, delAddress; require('../../../../utils/api', utils => { findUserAddress = utils.findUserAddress; delAddress = utils.deleteAddress; }, ({mod, errMsg}) => { console.error(`path: ${mod}, ${errMsg}`) })
- Promise方法
/* promise形式 */ (async function(){ let utils = await require('../../../../utils/api') console.log(utils) findUserAddress = utils.findUserAddress; delAddress = utils.deleteAddress; })()
8.7 分包效果演示
8.8 官网对应地址
https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
9. 小程序转发分享
9.1 分享实现
- Button组件设置open-type为share
<button open-type=’share’ ></button>
9.2 自定义分享内容
- 生命周期回调中onShareAppMessage回调中return 对象设置自定义内容
9.3 设置体验权限
- 开发阶段分享给微信好友,默认没有体验权限,无法打开分享小程序,需要在开发页面设置
- 最多添加15个微信好友
10. 小程序支付流程
10.1 支付流程官网图解
10.2 支付流程详细说明
- 用户在小程序客服端下单
- a)用户标识token
- b)商品信息: id,数量,附属信息(备注等)
- c)地址信息
- 小程序客户端发送下单支付请求给商家服务器
- a)获取商家订单id
- 商家服务器发送请求调用统一下单API获取预支付订单信息
- a)接口地址: https://api.mch.weixin.qq.com/pay/unifiedorder
- b)需要携带参数
- 用户openid
- 商户id
- 商户订单id
- 。。。
- 商家对预支付信息签名加密后返回给小程序客户端
- a)签名方式: MD5
- b)签名字段:小程序ID, 时间戳, 随机串,数据包,签名方式
- c)参考地址: https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3
- 用户确认支付(鉴权调起支付)
- a)API:
wx.requestPayment()
- b)鉴权通过后客户端调起输入框,用户输入支付密码
- c)注意:模拟器上会弹出二维码需要使用当前开发者微信扫码进行支付操作
- a)API:
- 微信服务器返回支付结果给小程序客户端
- a)支付成功后客户端发送请求给商家服务器查询订单信息
- b)根据订单信息决定如何跳转页面及展示信息给用户
- 微信服务器推送支付结果给商家服务器端
10.3 官网对应地址
https://pay.weixin.qq.com/wiki/doc/apiv3_partner/open/pay/chapter2_8_2.shtml
10.4 描述
整体流程:
-
用户下单,发请求给商家服务器(这一步前端做),商家服务器生成订单,然后给腾讯服务发请求,生成预付单,生成腾讯生成预付单的目的是为了知道这个订单要收多少钱,腾讯服务知道收多钱之后反馈给商家服务器,生成支付签名信息返回给小程序
-
小程序端接收到商家返回的支付签名信息,调用
wx.requestPayment()
发起微信支付(这一步前端做) -
发起之后要去腾讯服务鉴权,鉴定有没有实名、有没有绑定银行卡,鉴权成功之后告诉小程序可以调起微信支付,此时要去弹出密码输入框(这一步是调用完
requestPayment
)小程序自己和腾讯服务的交互 -
小程序弹出密码弹框,用户输入密码,授权付款,钱在腾讯服务上,所以授权要发送给腾讯服务,腾讯服务接到授权后,会把用户账号中的款扣了,把钱划给商家,返回支付成功告诉用户,提示"支付成功",这里的支付成功可以理解为"扣款成功"(这时会弹一个弹框,微信弹的)
在这个步骤的同时,会异步告诉商家服务,该用户已经付款,可以发货
-
点击微信弹出弹框确认之后,要回到商家的小程序,小程序也要提示用户"订单支付成功",所需小程序发请求给商家服务,商家服务接到请求之后,找腾讯服务确认用户是否支付成功,确认之后,返回给用户支付成功的数据,小程序展示"订单支付成功"页面
前端步骤:
-
调用创建订单接口,创建出订单,返回
orderId
-
拿着 orderId 获取支付信息
-
拿着支付信息调用
wx.requestPayment()
去支付只有支付成功之后,才会走
wx.requestPayment()
的 success 回调 -
在支付成功之后,调用接口查询订单状态(已支付),跳转支付成功页
项目中使用的
1.导航设置★
app.json
{
"pages":[
"pages/index/index"
],
"window":{
"navigationBarBackgroundColor": "#9c0211",
"navigationBarTitleText": "慕尚花坊",
"navigationBarTextStyle":"white"
},
}
2.小程序中的ui
2.1. swiper 轮播
<swiper
class="banner-container"
indicator-dots
indicator-color="#fff"
indicator-active-color="#ff734c"
autoplay
circular
interval="2200"
duration="400"
>
<swiper-item
class="banner-item"
wx:for="{{ bannerList }}"
wx:key="id"
>
<image class="banner-img" src="{{ item.imageUrl }}"></image>
</swiper-item>
</swiper>
2.2. image 组件
<view class="action">
<image class="action-img" src="{{backgroundImg}}" mode="widthFix"></image>
</view>
注意: image 组件的 mode="widthFix" 是设置宽度,保持图片的宽高比不变,自己去算高度
2.3scroll-view 的使用
页面宽高设置100%是相对于父级的,而父级是 page 这个元素,这个元素需要设置 宽高100%才可以,这个元素样式在 app.wxss 中设置,这是个全局的,每个页面的根元素都是 page 这个元素
<!-- scroll-view 如果要使用flex布局,需要设置enable-flex属性 -->
<view class="category-container">
<view class="menu">
<scroll-view
class="menu-list"
scroll-y
>
<view class="menu-item active">
鲜花玫瑰
</view>
<view class="menu-item">
鲜花玫瑰
</view>
<view class="menu-item">
鲜花玫瑰
</view>
<view class="menu-item">
鲜花玫瑰
</view>
</scroll-view>
</view>
注意:scroll-view 如果要使用flex布局,需要设置enable-flex属性
2.4 button
-
button 组件添加
open-type="chooseAvatar"
属性点击才能展示出选择头像的弹框 -
input 组件添加
type="nickname"
属性才能弹出选择昵称的弹框
3.封装 request.js 文件★
function request ({
url,
method = 'GET',
data,
header = {},
timeout = 30000
}) {
wx.showLoading({ title: '加载中' }); // 显示loading
const baseURL = `https://gmall-prod.atguigu.cn`
header = {
'content-type':'application/json',
...header
}
// 获取个人信息需要携带token
let token = wx.getStorageSync("TOKEN");
if (token) {
header.token = token
}
return new Promise((resolve, reject) => {
// wx.request 微信提供的,直接用,没有跨域这一说
wx.request({
url: baseURL + url, // 请求的url
method, // 请求方式
data, // 携带数据
header, // 请求头
timeout, // 超时时间
dataType: 'json', // 数据类型是json
responseType: 'text', // 响应类型是文本
success: (response) => { // 请求成功之后会执行success回调
let res = response.data // 拿到响应体(也就是后端返回的数据,包含code、data、message)
if (res && res.code == 200) {
resolve(res.data)
} else if (res.code == 208) { // 未登录的兜底处理,只要返回code是208都去登录页
wx.showModal({
title: '警告',
content: '未登录,请先登录',
showCancel: true,
cancelText: '取消',
cancelColor: '#000000',
confirmText: '确定',
confirmColor: '#3CC51F',
success: (result) => {
console.log(result)
if(result.confirm){ // 点击确认跳转登录页
wx.navigateTo({
url: '/pages/login/login'
});
}
}
});
} else {
// 弹出提示框
wx.showToast({ // 给用户提示
title: '请求失败',
icon: 'error', // none success error
// image: '/static/images/1.png',
duration: 1500
});
console.error(res) // 给程序员看的
reject(res || '请求失败')
}
},
fail: (err) => { // 请求失败执行的回调(断网的时候会走到fail中,超时也会只有fail,url错误(指url不是字符串)也会走fail)
wx.showToast({ // 给用户提示
title: '请求失败',
icon: 'error',
duration: 1500
});
console.error(err) // 给程序员看的
reject(err)
},
complete: () => { // 不管成功失败都会执行的回调
wx.hideLoading(); // 隐藏loading
}
});
})
}
export default request
4.关于路径映射@★
在 app.json 中配置
{
"resolveAlias": {
"@/*": "/*"
},
}
5. 底部tabbar 配置★
地址: https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html#tabBar
app.json 文件中配置
"tabBar": {
"color": "#333",
"selectedColor": "#ff582f",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "/static/tabbar/home-icon1.png",
"selectedIconPath": "/static/tabbar/home-icon1-1.png"
},
{
"pagePath": "pages/category/category",
"text": "分类",
"iconPath": "/static/tabbar/home-icon2.png",
"selectedIconPath": "/static/tabbar/home-icon2-2.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "/static/tabbar/home-icon3.png",
"selectedIconPath": "/static/tabbar/home-icon3-3.png"
},
{
"pagePath": "pages/personal/personal",
"text": "我的",
"iconPath": "/static/tabbar/home-icon4.png",
"selectedIconPath": "/static/tabbar/home-icon4-4.png"
}
]
},
6.分页处理★onReachBottom的使用
onReachBottom的使用 页面触底回调
-
页面触底的时候要发送请求,需要页面触底的回调(于data配置项同级)
data: { ...... status: 'more' // 页面发请求的状态,总共有以下几个值: 'more'更多 'no-more'没有更多 'loading'加载中 'error'错误 }, // 页面触底回调 onReachBottom() { if (this.data.status == 'no-more') { return } // 翻页 this.setData({ page: this.data.page + 1 }) this.getGoodsList() }, async getGoodsList() { this.setData({ status: 'loading' }) // 组转数据 const { page, limit, category2Id } = this.data let data = {} if (category2Id) { data.category2Id = category2Id } // 发送请求 try { let result = await reqGoodsList(page, limit, data) let goodsList = this.data.goodsList.concat(result.records) // 之前列表中的值不能清空 let status = 'more' if (goodsList.length == result.total) { // 当获取到所有的数据之后,状态改为no-more status = 'no-more' } ......
这里使用 goosList.length 和 totoal 去判断也可以