天天看点

微信小程序属性剖析:wx-key就这么重要吗?

今天,就想和各位说说微信小程序中的【臂膀】——​

​wx-key​

​。

微信小程序属性剖析:wx-key就这么重要吗?

毫无疑问,wx-key在微信小程序中可谓是“大出风头”,这一点尤其在for循环中体现出来。但wx-key的作用,你真的了解吗?

事实上,作为“唯一标识”,微信小程序也极力提倡在一些组件中使用

我们先来写一个简单的list列表:

//wxml
<block wx:for="{{arr}}">
  <view>{{item}}</view>
</block>

//js-data
data:{
  arr:['wxml','js','wxss','json']
},      
微信小程序属性剖析:wx-key就这么重要吗?

现在,我们给它加上索引:

//wxml
<block wx:for="{{arr}}">
  <view>{{index}}-{{item}}</view>
</block>      

微信小程序for循环默认每一项是一个“item”,默认每一项的索引为“index”。

当然,也可以通过​​

​wx:for-item​

​重新设置(每一项的名称)。

上面是wx-for循环的使用,

为了更好的展示wx:key的作用,我们给每一项前面加个【复选框】,并增加一个button按钮用来对list进行“随机排序”:

//wxml
<block wx:for="{{arr}}" wx:for-item="data">
  <view><checkbox />{{data}}</view>
</block>
<button bindtap="sort">随机排序</button>      
微信小程序属性剖析:wx-key就这么重要吗?
//js-随机排序代码(本文所有“随机排序”皆用此代码)
sort(){
  const len=this.data.arr.length
  for(let i in this.data.arr){
    let x=Math.floor(Math.random()*len)
    let y=Math.floor(Math.random()*len)
    let temp=this.data.arr[x]
    this.data.arr[x]=this.data.arr[y]
    this.data.arr[y]=temp
  }
  this.setData({
    arr:this.data.arr
  })
},      
微信小程序属性剖析:wx-key就这么重要吗?

重点来了,现在我随机勾选两项,然后按下button按钮:

微信小程序属性剖析:wx-key就这么重要吗?

我们会“惊恐”的发现:不管怎样,选中的都是“第二项”和“第四项”;但显然,我们希望选中的只是最开始“第二项”和“第四项”对应的数据!

其实,这无疑是“数据优先”的一个特点:从始至终我们都在操控数据,而无关结构

当然,这也是wx:key的作用之一:

正式篇:wx:key的解析

可能有的初学者会发现,有的地方完全“没必要”加上wx:key,而有的地方却必须要用?

这是【数据项是否发生变化】的区别。

所谓key —— 钥匙。正如“一把钥匙对应一把锁”。当一个数据项需要保证(持)他自己的【特征】,或者说【状态】时,才需要为其添加“key属性”。

我们改写一下上面的代码:

//wxml
<block wx:for="{{arr}}" wx:for-item="data" wx:key="{{index}}">
  <view><checkbox />{{data}}</view>
</block>
<button bindtap="sort">随机排序</button>      

前面说过,微信中for循环默认每一项“下标”用index显示。

然后我们会发现:毫无作用。

是key坏了么?

还是不应该加index?

但是不是说为每一项加一个“唯一标识”就行么,难道下标不是?

微信小程序属性剖析:wx-key就这么重要吗?

其实还真不行:“前面说了,for循环索引是index” —— 坏就坏在这句话上:索引本来就是“不变的”啊。

这么说吧:比如这里的arr数组,索引永远是0、1、2、3,哪怕元素改变了,下标却并不“被携带”。

这有点像什么呢?

“索引是数组为元素(位置)定下的索引,而不是元素的索引”

遇见这种情况我们就需要用到另一个关键字 —— ​

​*this​

​,用于小程序的for循环中,作为“指针”指向每一项自身:

//wxml
<block wx:for="{{arr}}" wx:for-item="data" wx:key="*this">
  <view><checkbox />{{data}}</view>
</block>
<button bindtap="sort">随机排序</button>      
微信小程序属性剖析:wx-key就这么重要吗?

现在就可以了!

由此可见:key属性必须是“关乎数据项自身的”、“独一无二的”。

我们不妨来看另一种情况,把数据变“复杂”一些:

//js-data
data:{
  arr:[{
    id:1,
    name:'wxml'
  },{
    id:2,
    name:'js'
  },{
    id:3,
    name:'wxss'
  },{
    id:4,
    name:'json'
  }]
},      

好吧,现在又回到“解放前”。

不过有了上面的经验,我们知道:这是key不到位的缘故;

但现在数据项变成了一个一个的对象了,还能和以前一样吗?

//wxml
<block wx:for="{{arr}}" wx:for-item="data" wx:key="{{id}}">
  <view><checkbox />{{data}}</view>
</block>
<button bindtap="sort">随机排序</button>