需求
在 Vue 中,對組件進行循環都需要加入key以便“就地復用”,可是在某些情況下,我們需要新建多個對象,而這些對象不是從后端獲取到的,而是前端生成的,沒有唯一值,且 Vue 目前版本只允許字符串,數字作為組件的 key。
方案
簡單的組件
例如
export?default{
methods:?{
addSometing?()?{????????????????this.items.push({????????????????????//?一些屬性
someProp
})
}
}
}
簡單的組件,對 items 進行 CRUD 都是可以識別出來。不會影響界面的顯示。
復雜的組件
但是對于一些復雜的組件 Vue 是識別不出來的,而且在刪除時候會發生錯亂。
所以需要這樣寫
export?default{
methods:?{
addSometing?()?{????????????????this.items.push({
id:?getUidFunction(),????????????????????//?一些屬性
someProp
})
}
}
}
在創建時候添加唯一的 key —— id ,并且在上傳的時候刪除數組的 id
缺點
很難判斷你所寫的組件究竟是復雜還是簡單,但在數組對象中添加唯一的 id 且必須在上傳之前去除它,這終究不是一個好的解決方案。
更好的方法 WeakMap
思考
在ruby語言中,我們可以唯一確定這個對象,因為每個對象新建后都有一個唯一值確定該對象。但是 js 卻沒有這種語言特性。所以我們要從這方面入手考慮。
WeakMap的作用
WeakMap針對于普通的 Map 有兩點特殊之處
1、WeakMap只接受對象作為鍵名( null 除外),不接受其他類型的值作為鍵名。
2、WeakMap的鍵名所指向的對象是弱引用,不計入垃圾回收機制。
重點在于 如果刪除了WeakMap的鍵名所指向的對象,無需手動刪除應用。
那么 思考后代碼如下//?唯一keylet?uKey?=?1//?弱引用Mapconst?uidMap?=?new?WeakMap()function?getUniqueKey?(obj)?{????if?(!uidMap.has(obj))?{
uidMap.set(obj,?uKey++)
}????return?uidMap.get(obj)
}//?為了簡單直接使用插件const?uidPlugin?=?{
install?(Vue)?{
Vue.prototype.$uid?=?getUniqueKey
}
}if?(typeof?window?!==?'undefined'?&&?window.Vue)?{????window.Vue.use(uidPlugin)
}export?{?uidPlugin?}
在復雜的組件可以這樣使用
無需添加唯一的 id 以及刪除 id ,即插即用且不影響垃圾回收。完美!
WeakMap ?其他使用場景
1、標識 對象
2、緩存與對象相關的 屬性
3、為對象添加監聽器
總結
新的特性對應新的解決方案,雖然js不是一門優秀的編程語言,但是js卻擁有著及其優秀的社區,社區使得js可以不斷進步。
作者:jump--jump
來源:https://my.oschina.net/wsafight/blog/1803004