1、小程序页面层级不能超过10层
微信小程序路由层级限制在9层,不能超过10层 业务流程比如:首页-搜索结果页-商品详情页-商品详情页-商品详情页-商品详情页-商品详情页...一不小心就超过10层了,要解决这个问题 有如下方案: 1.当页面栈到达第9层,提示用户(贝壳找房的小程序就是这样) 2.自己封装无限层级,做个空白的中间页
navigator: {
// 小程序支持打开的页面层数
maxLevel: 9,
// 中间跳转页
middlePage: '/pages/navigator/middle',
// 历史堆栈
historyStack: [],
// 跳转
navigateTo: function (route, reLaunch) {
// 是否关闭所有页面,打开到应用内的某个页面
reLaunch = typeof reLaunch !== 'undefined' ? true : false;
if (reLaunch) {
wx.reLaunch({
url: route.url
})
return
}
// console.log('util.navigator.navigateTo:', route)
// 小程序路由堆栈
let pages = getCurrentPages()
// console.log('util.navigator.navigateTo {pages}:', pages)
// console.log('util.navigator.navigateTo {pages.length}:', pages.length)
// 当前页面路由
let currentPage = pages[pages.length - 1];
// console.log('util.navigator.navigateTo {currentPage}:',currentPage)
if (pages.length < this.maxLevel - 1) { // 小于倒数第二层时
wx.navigateTo({
url: route.url
})
} else if (pages.length == this.maxLevel - 1) { // 等于倒数第二层时
this.historyStack.push(currentPage)
// console.log('util.navigator.navigateTo {this.historyStack}:', this.historyStack)
wx.redirectTo({
url: this.middlePage + '?url=' + encodeURIComponent(route.url)
})
} else { // 等于最后一层时
this.historyStack.push(currentPage)
// console.log('util.navigator.navigateTo {this.historyStack}:', this.historyStack)
wx.redirectTo({
url: route.url
})
}
},
},
2、微信生成小程序二维码 scene 参数过长的方法
小程序二维码 scene 参数限定长度为 32 位字符,但是实际开发中可能有很多的参数需要传递,比如pages/index/index?url=xxx%2F%23%2Fquick-ask%3&a=1%2F%23%2Fquick-ask%3&b=2&c=3%2F%23%2Fquick-ask%3,就需要通过特殊处理之后才能使用,常见方式如下
1.与后端约定好这个详情页scene值是个伪字符串 直接接口处理,返回正确的信息
2.短参数(写个中间件拦截onload函数的options,判断有无scene值,如果有请求接口换取完整页面参数,再去调用接口)
3、小程序生命周期-热启动/冷启动及其相关参数获取
-
冷启动: 首次打开小程序;或小程序销毁后打开,此时小程序需要重新加载启动,即冷启动。(冷启动会触发app.js中的onLaunch生命周期函数)
-
热启动: 点击右上角胶囊退出、或者home键离开微信、或者左右滑动返回到微信等动作,都是热启动,并没有销毁小程序, 如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动。(所以热启动不会触发onLaunch函数,但会触发onShow函数
在app.js调用该函数
/** 检测当前的小程序,是否是最新版本,是否需要下载、更新 */
checkUpdateVersion: function () {
// console.log('util.checkUpdateVersion')
//创建 UpdateManager 实例
const updateManager = wx.getUpdateManager()
//检测版本更新
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
if (res.hasUpdate) {
//监听小程序有版本更新事件
updateManager.onUpdateReady(function () {
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success(res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新版本下载失败
wx.showModal({
title: '已经有新版本咯~',
content: '请您删除当前小程序,到微信 “发现-小程序” 页,重新搜索打开呦~',
})
})
}
})
}
4、分包的问题
为什么需要分包
微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地的,这种策略可以缓解页面跳转时白屏的问题。同时微信还对小程序代码包大小设置了 2M (最初只有 1M)的上限来确保小程序能有还不错的启动速度。
分包应该注意的地方
-
微信小程序每个分包的大小是 2M,总体积一共不能超过 20M;
-
需要尽量保持主包只加载必须的内容,主要包括一些必须公共资源/JS 脚本,tabBar 页面,最好只包括这些页面;
-
分包越早越好,如果后期进行分包,不然后期进行分包,就要处理前期被内部及外部调用的地址;
- 对于已经对外放出的页面就更没法修改了;
- 页面不能通过路由进行重定向,也就是路由与页面位置是绝对对应的;
-
主包不可以引用子包内容,子包只可以引用自己包内和主包内的内容,子包内不能嵌套子包;
- 独立分包是小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载,这个我们通常不会用到。
-
子包预下载:开发者可以通过配置,在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。
5、 setData 数据量不能超过2M
当 setData 过大时会提示错误
vdSyncBatch 数据传输长度为 2260792 已经超过最大长度 1048576
复制代码
因为setData设置的数据量是有限制的,单次设置的数据大小不得超过1024kb,否则就会出现如上错误
解决方案:将数组转成二维数组后进行setData,并且需要修改wxml的循环结构,多套一层循环。
伪代码
data:{
currentpage:0,// 当前页数
list:[], // 数据源
},
getListData:function(){
// 本次加载的数据
let _list = [];
... setData({ [list[' + currentpage + ']']: _list, });
}
6、超长滚动列表,上拉加载过多后内存溢出性能优化
当列表页面上拉加载数据到一定量时,占内存过高,导致小程序卡顿甚至黑屏关闭。
解决思路:让不在当前窗口区域内的内容wxml结构移除。
操作思路:封装一个列表item的容器组件,利用 createIntersectionObserver 的 relativeToViewport 的 observe 方法监听当前 item 所在位置,进行移除或者插入
核心代码
组件skeleton.wxml
<view class="list-item" id="list-item-{{uniqueId}}" style="min-height: {{height}}px;">
<block wx:if="{{showSlot}}">
<slot></slot>
</block>
</view>
复制代码
组件skeleton.js
...
ready() {
// 修改了监听是否显示内容的方法,改为前后showNum屏高度渲染
// 监听进入屏幕的范围relativeToViewport({top: xxx, bottom: xxx})
const { windowHeight = 667 } = systemInfo()
const showNum = this.data.showNum //超过屏幕的数量,目前这个设置是上下2屏
try {
this.IntersectionObserver = this.createIntersectionObserver()
this.IntersectionObserver.relativeToViewport({
top: showNum * windowHeight,
bottom: showNum * windowHeight
}).observe(`#list-item-${this.data.uniqueId}`, res => {
let { intersectionRatio } = res
if (intersectionRatio === 0) {
console.log('【卸载】#', this.data.uniqueId, '超过预定范围,从页面卸载')
this.setData({ showSlot: false })
} else {
console.log('【进入】#', this.data.uniqueId, '达到预定范围,渲染进页面')
this.setData({
showSlot: true,
height: res.boundingClientRect.height
})
}
})
} catch (error) {
console.log(error)
}
...
7、图片处理
图片资源放在cos上,压缩加裁剪
/**
* oldurl 图片地址
* width 图片裁剪的宽
* height 图片裁剪的高
* identification 图片裁剪方式
* multiples 裁剪倍数
*/
cropimg: function (oldurl, width, height, identification,multiples) {
let newurl = ''
if (identification == 'crop') {
newurl = oldurl + '?imageMogr2/thumbnail/!' + width*(multiples?multiples:1.5) + 'x' + height*(multiples?multiples:1.5) + 'r/interlace/0|imageMogr2/gravity/center/crop/' + width*(multiples?multiples:1.5) + 'x' + height*(multiples?multiples:1.5) + '/auto-orient'
// newurl =`${oldurl}?imageView2/1/w/${width*(multiples?multiples:1.5)}/h/${height*(multiples?multiples:1.5)}`
//
} else if (identification == 'cropwidth') {
newurl = oldurl + '?imageMogr2/thumbnail/' + width + 'x/auto-orient'
}
return newurl
}
8、小程序分享朋友圈
目前仅安卓分享朋友圈有效 如果分享朋友圈的页面需要走wx.login授权接口的话 需要判断
const { scene, mode } = wx.getLaunchOptionsSync()
// mode === 'singlePage' OR scene === 1154 && isIOS