文档中关于wx:key的描述如下:
wx:key
的值以两种形式提供
字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字
——————————————————————————————————————————————————
之前没太注意这块,现在发现项目里很多地方都是这么写的:
<view wx:for="{{ list }}" wx:key="{{ item.id }}">......</view>
是想将表达式{{ item.id }}的返回值作为唯一值
我的问题是,这种写法对么?列表元素可以成功复用么?
根据文档1,“代表在 for 循环的 array 中 item 的某个 property”。实际上,有没有可能把表达式{{ item.id }}的返回值当成了property,然后key用的是item[ property ],也就是 item[ item.id ] ?或者有没有可能最后key用的是item["{{ item.id }}"]?那应该都是undefined,为啥我的示例里都没有报错呢?
提供一个示例,https://developers.weixin.qq.com/s/5s3XdomT7w8T
这绝对不是一个少见的问题,我看社区里很多人都这么用了
—————————————————————————————————————————————————
更新一下,加一个示例,这个示例的现象也不太正常:https://developers.weixin.qq.com/s/AytL4pmM7k8p
—————————————————————————————————————————————————
原来这个问题存在快1年了
这篇文章的作者遇到的现象是诡异的,而回答给他的解决方案,瞎扯
https://developers.weixin.qq.com/community/develop/doc/00062ec7eecea8f64427829ab5b400
这篇文章官方回答了,但是太言简意赅,导致底下的回答还是在瞎扯
https://developers.weixin.qq.com/community/develop/doc/000ee2aca04a102195278397e51c04
这篇文章,从头到位都是瞎扯
其实我上面的瞎扯都想用放屁来代替的,就这么个问题,磨磨唧唧弄了这么久,大部分人都还是在瞎搞。是当初设计的锅?还是文档没写清楚的锅?还是因为官方的不重视?还是社区质量太差?
即便严格按照文档的说法,我上面的两个示例还是解释不通的,哎。。。
wx:key 里有花括号是无效的写法,官方示例的错误写法我们梳理一下。 按照你上面的例子,正确写法是 wx:key="id"
嗯的,正确的写法我知道的。我更想知道的是错误写法时候发生了什么。问两个问题:
一、我提供的第二个示例,有效的wx:key会导致触发自定义组件的moved生命周期。无效的wx:key,自定义组件attached、ready、moved、detached生命周期都没有被触发,也就是说自定义组件还是被复用了?这里的逻辑是什么
二、如果没有一个唯一的id,又不想在控制台看到报错,wx:key该怎么写?比如
<view wx:for="{{[1, 1, 1, 1]}}" wx:key="???">不能被复用,但是不想看到警告</view>
一、在 key 无效的情况下,我们会尝试去复用已有的节点(包括自定义组件)。这个过程会更改自定义组件属性。
二、现在应该都会给警告。
List 结构是这种,怎么指定 wx:key 呢?(我需要a里面的id)
[ { 'a': { 'id': 1} 'b': {'name': 'xxx'} }, { 'a': { 'id': 2} 'b': {'name': 'yyyy'} } ]
你好,我这边用了wx:key="unique",但是重新打乱了顺序之后,input的值被改回去了?这是怎么回事,我按照网上的一个例子做的也不行
<input wx:for="{{inputList}}" wx:for-item="dItem" wx:key="unique" value="id:{{dItem.id}}" />
<button bindtap="switch">switch</button>
<button bindtap="addToFront">addToFront</button>
Page({
data: {
logs: [],
inputList: [{
"id": 1,
"unique": "unique1"
},
{
"id": 2,
"unique": "unique2"
},
{
"id": 3,
"unique": "unique3"
},
{
"id": 4,
"unique": "unique4"
},
]
},
addToFront: function(e) {
const length = this.data.inputList.length + 1;
this.data.inputList = [{
id: length,
unique: 'unique_' + length
}].concat(this.data.inputList)
this.setData({
inputList: this.data.inputList
})
},
switch: function(e) {
const length = this.data.inputList.length
for (let i = 0; i < length; ++i) {
const x = Math.floor(Math.random() * length)
const y = Math.floor(Math.random() * length)
const temp = this.data.inputList[x]
this.data.inputList[x] = this.data.inputList[y]
this.data.inputList[y] = temp
}
this.setData({
inputList: this.data.inputList
})
},
wx:key="{{ item.id }}" 当然是错的啦,key就是属性名,这里写成item.id,那就是拿item.id的值当key,当你改变数组的时候,它会报key相同的警告,
正确应该是wx:key="id"
项目里很多地方都这么用了,不会报警告的,这个是确定的。你的意思是wx:key="{{item.id}}",会先解析花括号里的表达式,然后把这个表达式的值当成key,也就是说最后列表项的唯一标识会是item[ item[id] ],一般来说就是undefined,是这意思吧?
嗯的,我知道正确的写法是啥,但是我更想知道,在错误写法的时候发生了什么。
我提供了两个示例,有针对性的,可以看看
那个key是用来复用组件的,如果key写的不对,渲染时则找不到对应的组件,组件就会重新创建而不会复用,仅此而已
那你再看看第二个示例,看是这样么
只是视图层重新渲染了,逻辑层并没有变化
“只是视图层重新渲染了,逻辑层并没有变化”
那岂不是比用wx:key="unique"还好?wx:key的意义何在?
视图层自己就变了?mvvm的思路不就是逻辑层决定视图层?
哎老弟,对待知识应该严谨,你再想想是真懂了么?
写惯了vue当初也有这个疑问