这是我参与更文挑战的第7天,活动详情查看: 更文挑战
代码包大小控制
- 勾选开发者工具中“上传代码时,压缩代码”选项
- 及时清理无用的代码和资源文件(包括无用的日志代码)
- 减少资源包中的图片等资源的数量和大小(理论上除了小 icon,其他图片资源从网络下载),图片资源压缩率有限
采用分包加载机制
按照小程序功能对首页以及经常用到的页面放在主包中,其余的可以根据功能和访问频率进行分包
采用分包预加载技术
避免使用不当 setData
- 不要过于频繁调用 setData,应考虑将多次 setData 合并成一次 setData 调用
- 与界面渲染无关的数据最好不要设置在 data 中,可以考虑设置在 page 对象的其他字段下
- 切勿在后台页面进行 setData
更好的分页加载数据的方式
相对于上面的加载方式,只需要在数据存储上做一些小的改变,就能实现加载更多的数据。这个方法就是再增加一个数组,用来存放数据。上一个方法是一个数组中存放所有的数据,数据量很容易就会变大。这个方法,将每一页请求过来的数据的引用放到一个新的数组 dataArray 内。dataArray[0]存放第一页数据,dataArray[1]存储第二页数据。请求新一页,都只需要更新一组数据,这样 set 的数据就不会超过微信小程序允许的长度。这个方法首先在 loadInitData 时,清空 dataArray,防止新数据与原数据冲突。然后将这一页数据放到 dataArray[0]中即可。
loadInitData: function () {
var that = this
var currentPage = 0; // 因为数组下标是从0开始的,所以这里用了0
var tips = "加载第" + (currentPage+1) + "页";
console.log("load page " + (currentPage + 1));
wx.showLoading({
title: tips,
})
// 刷新时,清空dataArray,防止新数据与原数据冲突
that.setData({
dataArray: []
})
// 请封装自己的网络请求接口,这里作为示例
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相应的json数据
var articles = data.data; // 接口中的data对应了一个数组,这里取名为 articles
var totalDataCount = articles.length;
// console.log(articles);
console.log("totalDataCount:"+totalDataCount);
that.setData({
["dataArray["+currentPage+"]"]: articles,
currentPage: currentPage,
totalDataCount: totalDataCount
})
}
})
},
在页面的渲染上,与上面的方法也有一些小差别,使用了 2 个 for 循环来渲染数据。
<scroll-view scroll-y="true" style = "height:100%;position: relative;" scroll-into-view="{{toView}}" scroll-with-animation = "true">
<view id = "top"></view>
<block wx:for="{{dataArray}}" wx:for-item="articles" wx:for-index="dataArrayIndex">
<block wx:for="{{articles}}" wx:for-item="item" wx:key="{{item.id}}" wx:for-index="index">
<template is = "articles" data='{{item:item,index:index,dataArrayIndex:dataArrayIndex}}'/> <!--将item和index都传到模版里去,不然模版中获取不到index-->
</block>
</block>
<view id = "bottom"></view>
</scroll-view>
加载下一页数据时,根据这页的下标,将这页的数据放到对应下标的 dataArray 中。
/**
* 加载下一页数据
*/
loadMoreData: function () {
var that = this
var currentPage = that.data.currentPage; // 获取当前页码
currentPage += 1; // 加载当前页面的下一页数据
var tips = "加载第" + (currentPage + 1) + "页";
console.log("load page " + (currentPage + 1));
wx.showLoading({
title: tips,
})
// 请封装自己的网络请求接口,这里作为示例就直接使用了wx.request.
wx.request({
url: 'https://raw.githubusercontent.com/lanfeng1993/LoadDataDemo/master/data/data.json',
data: {
},
header: {
'content-type': 'application/json'
},
success: function (res) {
wx.hideLoading();
var data = res.data; // 接口相应的json数据
var articles = data.data; // 接口中的data对应了一个数组,这里取名为 articles
// 计算当前共加载了多少条数据,来证明这种方式可以加载更多数据
var totalDataCount = that.data.totalDataCount;
totalDataCount = totalDataCount + articles.length;
console.log("totalDataCount:" + totalDataCount);
// 直接将新一页的数据添加到数组里
that.setData({
["dataArray[" + currentPage + "]"]: articles,
currentPage: currentPage,
totalDataCount: totalDataCount
})
}
})
},
这种方式加载同样的数据可以加载到 1400 条,再往下加载会抛出另一个异常:Uncaught Dom limit exceeded, please check if there's any mistake you've made.这个问题是因为小程序在这个页面渲染的 dom 结构太多了,已经超过了上限,这个问题目前没有找到什么解决方法。毕竟数据也是不能被无限加载的,小程序内也没有 app 中列表的复用的能力。不过相对于第一种方法,只能加载 240 条数据来说,这种方法能加载 1400 条数据,也还是可以的,不过加载了 1400 条数据后,这个列表滚动起来也是非常卡了。
使用自定义组件
自定义组件的更新只在组件内部进行,不受页面其他不能分内容的影响;比如一些运营活动的定时模块可以单独抽出来,做成一个定时组件,定时组件的更新并不会影响页面上其他元素的更新;各个组件也将具有各自独立的逻辑空间。每个组件都分别拥有自己的独立的数据、setData 调用。
避免不当的使用 onPageScroll
每一次事件监听都是一次视图到逻辑的通信过程,所以只在必要的时候监听 pageSrcoll
条件判断将 wx:if 换成了 hidden
在小程序中使用 wx-if,是基于局部渲染的形式。比如 wx:if 初始渲染条件为 false 时,框架什么都不会做;只有为真的时候才开始渲染该组件。而使用 hidden 在初始的时候就会渲染,它的值只是负责该组件的显示与隐藏。因此在切换的时候,wx:if 有更高的性能消耗,当我们项目需要频繁切换时,建议把 wx:if 换成了 hidden。
小程序中多张图片懒加载方案
由于小程序对用户内存使用进行了限制,如果一个页面的图片过多,会导致内存不足的内部错误。我在项目中用到的优化方案是:使用 scroll-view 实现分屏加载,然后给未加载的图片设置默认图片。 小程序文档中有新增 image 的 lazy-load 属性,当值为 true 时生效,注意:只针对 page 与 scroll-view 下的 image 有效。
截流
function throttle (fn, delay) {
// 利用闭包变量时效性
let timeout
let arg
return function () {
arg = arguments
if (!timeout) {
timeout = setTimeout(() => {
fn.apply(this, arg)
timeout = null
}, delay)
}
}
}
防抖
function debounce (fn, delay){
let timeout
return function(){
const args = arguments
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}