今天,就想和各位說說微信小程序中的【臂膀】——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']
},
現在,我們給它加上索引:
//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>
//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
})
},
重點來了,現在我隨機勾選兩項,然後按下button按鈕:
我們會“驚恐”的發現:不管怎樣,選中的都是“第二項”和“第四項”;但顯然,我們希望選中的只是最開始“第二項”和“第四項”對應的數據!
其實,這無疑是“數據優先”的一個特點:從始至終我們都在操控數據,而無關結構
當然,這也是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?
但是不是說爲每一項加一個“唯一標識”就行麼,難道下標不是?
其實還真不行:“前面說了,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>
現在就可以了!
由此可見:key屬性必須是“關乎數據項自身的”、“獨一無二的”。
我們不妨來看另一種情況,把數據變“複雜”一些:
//js-data
data:{
arr:[{
id:1,
name:'wxml'
},{
id:2,
name:'js'
},{
id:3,
name:'wxss'
},{
id:4,
name:'json'
}]
},
好吧,現在又回到“解放前”。
不過有了上面的經驗,我們知道:這是key不到位的緣故;
但現在數據項變成了一個一個的對象了,還能和以前一樣嗎?
是的。但是我們的數據中已經有了“唯一性表示” —— id了,又何必“捨近求遠”呢?
//wxml
<block wx:for="{{arr}}" wx:for-item="data" wx:key="{{id}}">
<view><checkbox />{{data}}</view>
</block>
<button bindtap="sort">隨機排序</button>