天天看點

微信小程式屬性剖析: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>