微信小程序:使用 wx:key 提升 wx:for 的渲染效率

更新日期: 2021-01-22 阅读次数: 37348 分类: 微信小程序

Now you can provide attr "wx:key" for a "wx:for" to improve performance

之所以加上 wx:key 会提升 wx:for 的渲染效率,原因是(我的初步理解)

  • 如果不加 wx:key, 在 setData 之后,如果 array 内的数据如果发生改变,会重新创建前端的渲染对象
  • 加上 wx:key,重新渲染时,只是将对应的对象重新排序。未发生变化的对象,不会重新创建

参考官方的解释

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

需要验证的问题

加上 wx:key 之后,会根据给定的 key 进行排序么?

写个简单的测试页面

<block wx:for="{{languages}}" wx:for-item="language" wx:key="id">
  <text class="log-item">{{ language.id }} . {{ language.name }}</text>
</block>

data: {
  languages: [
    {id: 1, name: 'php'},
    {id: 4, name: 'javascript'},
    {id: 3, name: 'golang'},
    {id: 2, name: 'python'},
    {id: 5, name: 'java'},
  ],
},

微信小程序 wx:key 测试结果

从测试结果来看,并不会影响到排序。

key 重名时是否会报错

data: {
  languages: [
    {id: 1, name: 'php'},
    {id: 4, name: 'javascript'},
    {id: 3, name: 'golang'},
    {id: 2, name: 'python'},
    {id: 5, name: 'java'},
  ],
},

click: function () {
	let language = {id: 5, name: 'kotlin'}
	let languages = this.data.languages
	languages.push(language)

	this.setData({
		languages: languages
	})
}

微信小程序开发工具只会报一个警告,并不会导致程序崩溃

VM6265:2 Do not set same key {5} in wx:key

比较奇怪的是,这个警告只有在重新渲染时才会报,如果初始化时就使用同样的 key,并不会导致警告。

wx:key 的值填写什么

参考官方文档:

https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/list.html

所以,评论中的说法并不对。我示例中的值 id 是正确的写法。

但是除了这种写法之外,还有一种写法。

wx:key 的值以两种形式提供

1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
2. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。

所以,两种写法的示例:

wx:key="id"
wx:key="*this"

注意:*this 这种写法,只适用于字符串数组,或者数字数组。否则会报错:

For developer:Do not set same key "[object Object]" in wx:key

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式

谈笑风生

stay-hungry

wx:key="id"应该改为  wx:key="{{item.id}}",这样才会按照id排序