背景
目前小程序会有不少的应用场景里会用到无限长列表的交互,当一个页面展示很多信息的时候,会造成小程序页面的卡顿以及白屏。原因有如下几点:
列表数据很大,首次 setData 的时候耗时高
渲染出来的列表 DOM 结构多,每次 setData 都需要创建新的虚拟树、和旧树 diff 操作耗时都比较高
渲染出来的列表 DOM 结构多,占用的内存高,造成页面被系统回收的概率变大。
因此就有长列表组件来解决这些问题
实现思路
核心的思路是只渲染显示在屏幕的数据,基本实现就是监听 scroll 事件,并且重新计算需要渲染的数据,不需要渲染的数据留一个空的 div 占位元素。
假设列表数据有100个 item,知道了滚动的位置,怎么知道哪些 item 必须显示在页面?因为 item 还没渲染出来,不能通过 getComputedStyle 等 DOM 操作得到每个 item 的位置,所以无法知道哪些 item 需要渲染。为了解决这个问题,需要每个 item 固定宽高。item 的宽高的定义见下面的 API 的createRecycleContext()的参数 itemSize 的介绍。
滚动过程中,重新渲染数据的同时,需要设置当前数据的前后的 div 占位元素高度,同时是指在同一个渲染周期内。页面渲染是通过 setData 触发的,列表数据和 div 占位高度在2个组件内进行 setData 的,为了把这2个 setData 放在同一个渲染周期,用了一个 hack 方法,所以定义 recycle-view 的 batch 属性固定为 batch="{{batchSetRecycleData}}"。
在滚动过程中,为了避免频繁出现白屏,会多渲染当前屏幕的前后2个屏幕的内容。
实现方法
step 1:下载源代码
直接通过 git 下载 wxa-plugin-canvas 源代码。
https://github.com/jasondu/wxa-plugin-canvas
step 2:将miniprogram_dist目录拷贝到自己的项目组件目录中
miniprogram\components\miniprogram_dist
首先设计界面
step 3:在 wxml 中使用组件
miniprogram/pages/my/UserPosterQrCodeService/index.wxml
首先放上poster的 id,用于显示后面将要生成的海报
<poster id="poster" config="{{posterConfig}}" bind:success="onPosterSuccess" bind:fail="onPosterFail">
</poster>
事件
<button bindtap="onCreatePoster">异步生成海报</button>
step 3:页面引入该组件
poster的 id需要引入组件,用来显示即将生成的海报
miniprogram/pages/my/UserPosterQrCodeService/index.json
{
"usingComponents": {
"poster": "/components/miniprogram_dist/poster/index"
}
}
step 4:js页面引入该插件:
异步调用需要引入该插件
miniprogram/pages/my/UserPosterQrCodeService/index.js
import Poster from '../../../components/miniprogram_dist/poster/poster';
step 5:添加配置信息posterConfig
(1)图片的域名添加到downloadFile合法域名中(开发设置-服务器域名-downloadFile合法域名)
登陆微信公众平台https://mp.weixin.qq.com,输入小程序的登陆邮件和密码,需用管理员微信扫码完成登陆,否则会提示“没有配置权限”。
选择开发-》开发设置-》开始配置,配置https域名
(2)在data中添加配置信息posterConfig
在生成海报前,需要准备一些用于海报的数据。
miniprogram/pages/my/UserPosterQrCodeService/index.js
data: {
url: '',
winWidth: 0,
winHeight: 0,
oneHeight: 0, // 风景图的高度
ewmWidth: 0, //二维码的高度
oneWidth: 0, //左右两边的空白
twoWidth: 0, //二维码和边框之间的距离
fontHeight: 0,
text1: '',
text2: '',
text3: '',
text4: '',
posterConfig: {
width: 750,
height: 1000,
backgroundColor: '#fff',
debug: false,
blocks: [
{
x: 0,
y: 10,
width: 750, // 如果内部有文字,由文字宽度和内边距决定
height: 120,
paddingLeft: 0,
paddingRight: 0,
borderWidth: 10,
borderColor: 'red',
backgroundColor: 'blue',
borderRadius: 40,
text: {
text: [
{
text: '金额¥ 1.00',
fontSize: 80,
color: 'yellow',
opacity: 1,
marginLeft: 50,
marginRight: 10,
},
{
text: '金额¥ 1.00',
fontSize: 20,
color: 'yellow',
opacity: 1,
marginLeft: 10,
textDecoration: 'line-through',
},
],
baseLine: 'middle',
},
}
],
texts: [
{
x: 0,
y: 180,
text: [
{
text: '长标题长标题长标题长标题长标题长标题长标题长标题长标题',
fontSize: 40,
color: 'red',
opacity: 1,
marginLeft: 0,
marginRight: 10,
width: 200,
lineHeight: 40,
lineNum: 2,
},
{
text: '原价¥ 1.00',
fontSize: 40,
color: 'blue',
opacity: 1,
marginLeft: 10,
textDecoration: 'line-through',
},
],
baseLine: 'middle',
},
{
x: 10,
y: 330,
text: '金额¥ 1.00',
fontSize: 80,
color: 'blue',
opacity: 1,
baseLine: 'middle',
textDecoration: 'line-through',
},
],
images: [
{
url: 'http://weixin.usdotnet.com/imgage/bgk_wanjiale.jpg',
width: 300,
height: 300,
y: 450,
x: 0,
// borderRadius: 150,
// borderWidth: 10,
// borderColor: 'red',
},
{
url: 'http://weixin.usdotnet.com/imgage/bgk_wanjiale.jpg',
width: 100,
height: 100,
y: 450,
x: 400,
borderRadius: 100,
borderWidth: 10,
},
],
lines: [
{
startY: 800,
startX: 10,
endX: 300,
endY: 800,
width: 5,
color: 'red',
}
]
}
},
step 6:添加生成事件处理函数
/**
* 异步生成海报
*/
onCreatePoster() {
// setData配置数据
this.setData({
posterConfig: this.data.posterConfig
}, () => {
Poster.create();
});
},
点击生成按钮后海报生成成功的回调函数,可以得到转换后海报图像文件
/**
* 生成海报成功-回调
* @param {} e
*/
onPosterSuccess(e) {
const {
detail
} = e;
this.setData({
//海报转换为图片的地址
//http://tmp/wx9b00e80b6177fc26.o6zAJs-f-7jP3_rHnfQa5Vtxy2A8.dSrboGDj1uun236dd799633794e88a71f099d536c474.png
posterImageUrl: detail,
isShowPosterModal: true
})
点击生成按钮后海报生成失败的回调函数
/**
* 生成海报失败-回调
* @param {*} err
*/
onPosterFail(err) {
console.info(err)
},
写一个wxml ,将图像显示出来,加上放大,保存等动作的处理。
wxa-plugin-canvas组件
组件原理说明文章
https://juejin.im/post/5b7e48566fb9a01a1059543f
使用案例
https://github.com/CavinCao/mini-blog
同类博客:
运用wxa-plugin-canva插件生成图片
https://blog.csdn.net/weixin_38710804/article/details/97927105
同类其他插件