vue和react項目中key的作用示例詳解
vue react對比新舊虛擬節(jié)點
vue和react都是采用diff算法來對比新舊虛擬節(jié)點,從而更新節(jié)點。
在交叉對比中,當新節(jié)點跟舊節(jié)點頭尾交叉對比沒有結果時,會根據新節(jié)點的key去對比舊節(jié)點數組中的key,從而找到相應的舊節(jié)點(這里對應的是一個key=>index的map映射)。
如果沒有找到就認為是一個新增節(jié)點。而如果沒有key,那么就會采用遍歷查找的方式去找到對應的舊節(jié)點,一種一個map映射,另一種是遍歷查找。相比而言,map映射速度更快。
vue部分源碼如下
//vue項目 src/core/vdom/patch.js -448行 //oldCh是一個舊虛擬節(jié)點數組 if(isUndef(oldKeyToIdx)){ oldKeyToIdx = createKeyToOldIdx(oldCh,oldStartIdx,oldEndIdx) } if(isDef(newStartVnode.key)){ //map方式獲取 idxInOld = oldKeyToIdx[newStartVnode.key] }else { //遍歷方式獲取 idxInOld = findIdxInOld(newStartVnode,oldCh,oldStartIdx,oldEndIdx) }
創(chuàng)建map函數
function createKeyToOldIdx(children,beginIdx,endIdx){ let i,key const map = {} for(i = beginIdx;i<=endIdx;i++){ key = children[i].key if(isDef(key)) map[key] = i } return map }
遍歷尋找
//sameVnode 是對比新舊節(jié)點是否相同的函數 function findIdxInOld(node,oldCh,start,end){ for(let i = start;i<end;i++){ const c = oldCh[i] if(isDef(c) && sameVnode(node,c)) return i } }
上面的結論是基于沒有key的情況diff速度會更快。確實,這種觀點沒有錯。沒有綁定key的情況下,并且在遍歷模版簡單的情況下,會導致虛擬新舊節(jié)點對比更快,節(jié)點也會復用。而這種復用是就地復用,一種鴨子辯型的復用。以下為簡單的例子:
<div id="app"> <div v-for="i in dataList">{{ i }}</div> </div> var vm = new Vue({ el:'#app', data:{ dataList:[1,2,3,4,5] } })
以上的例子,v-for的內容會生成以下的dom節(jié)點數組,我們給每一個節(jié)點標記一個身份id:
[ '<div>1</div>',//id:A '<div>2</div>',//id:B '<div>3</div>',//id:C '<div>4</div>',//id:D '<div>5</div>',//id:E ]
改變dataList數據,進行數據位置替換,對比改變后的數據
vm.dataList = [4,1,3,5,2]//數據位置替換 //沒有key的情況,節(jié)點位置不變,但是節(jié)點innerText內容更新了 [ '<div>4</div>',//id:A '<div>1</div>',//id:B '<div>3</div>',//id:C '<div>5</div>',//id:D '<div>2</div>',//id:E ] //有key的情況,dom節(jié)點位置進行了交換,但是內容沒有更新 // <div v-for="i in dataList" :key='i'>{{ i }}</div> [ '<div>4</div>',//id:D '<div>1</div>',//id:A '<div>3</div>',//id:C '<div>5</div>',//id:E '<div>2</div>',//id:B ]
增刪dataList列表項
vm.dataList = [3,4,5,6,7] //數據進行增刪 // 1、沒有key的情況,節(jié)點位置不變,內容也更新了 [ '<div>3</div>',//id:A '<div>4</div>',//id:B '<div>5</div>',//id:C '<div>6</div>',//id:D '<div>7</div>',//id:E ] // 2、有key的情況,節(jié)點刪除了A B節(jié)點,新增了F G節(jié)點 // <div v-for="i in dataLIST" :key='i'>{{ i }}</div> [ '<div>3</div>',//id:C '<div>4</div>',//id:D '<div>5</div>',//id:E '<div>6</div>',//id:F '<div>7</div>',//id:G ]
從以上來看,不帶有key,并且使用簡單的模版,可以更有效的復用節(jié)點,diff速度也是不帶key更加快速的,因為帶有key在增刪節(jié)點上有耗時。這就是vue文檔所說的默認模式。但是這個并不是key作用,而是沒有key的情況下可以對節(jié)點就地復用,提高性能。
這種模式會帶來一些隱藏的副作用,比如可能不會產生過度效果,或者在某些節(jié)點有綁定數據(表單)狀態(tài),會出現(xiàn)狀態(tài)錯位。vue文檔也說明了這個模式是高效的,但是只是適用于不依賴子組件狀態(tài)或臨時dom狀態(tài)(例如:表單輸入值)的列表渲染輸出
但是key的作用是什么?
key是給每個vnode的唯一id,可以依靠key,更快的拿到oldVnode中對應的vnode節(jié)點。
1、更準確
因為帶key就不是就地復用了,在sameNode函數a.key === b.key對比中可以避免就地服用的情況。所以會更加準確。
2、更快
利用key的唯一性生成map對象來獲取對應節(jié)點,比遍歷方式更快。
以上就是vue和react項目中key的作用示例詳解的詳細內容,更多關于vue react項目key作用的資料請關注腳本之家其它相關文章!
相關文章
vue腳手架創(chuàng)建項目時報catch錯誤及解決
這篇文章主要介紹了vue腳手架創(chuàng)建項目時報catch錯誤及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01VueX?mapGetters獲取Modules中的Getters方式
這篇文章主要介紹了VueX?mapGetters獲取Modules中的Getters方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08vue.config.js中configureWebpack與chainWebpack區(qū)別及說明
這篇文章主要介紹了vue.config.js中configureWebpack與chainWebpack區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09vue自定義指令和動態(tài)路由實現(xiàn)權限控制
這篇文章主要介紹了vue自定義指令和動態(tài)路由實現(xiàn)權限控制的方法,幫助大家更好的理解和學習vue,感興趣的朋友可以了解下2020-08-08vant的Loading加載動畫組件的使用(通過接口拿數據時顯示加載狀態(tài))
這篇文章主要介紹了vant的Loading加載動畫組件的使用,通過接口拿數據時顯示加載狀態(tài),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-01-01