在react中者甲,如果要渲染一個(gè)列表商佛,我們會(huì)用map()函數(shù)將數(shù)組循環(huán)處理然后渲染到DOM,在處理循環(huán)時(shí)整葡,“key” 是一個(gè)你需要包含的特殊字符串屬性件余。
很多時(shí)候,我們會(huì)使用當(dāng)前列表的索引為key,但這樣做真的好嗎?
要討論這個(gè)問題蛾扇,我們要從react的原理說起搏明,我們r(jià)eact的執(zhí)行步驟一般是:用state和jsx模板生成虛擬DOM创千,然后用虛擬DOM生成真實(shí)的 DOM,當(dāng)我們state發(fā)生變化時(shí),render函數(shù)執(zhí)行,生成新的 虛擬DOM谚鄙,然后比較新舊虛擬DOM的區(qū)別,找到區(qū)別疚鲤,然后直接操作DOM啸如,改變有區(qū)別的內(nèi)容,這樣比傳統(tǒng)的操作DOM成翩,極大的提升了性能觅捆。
再說虛擬DOM,虛擬DOM其實(shí)就是一個(gè)JS對(duì)象(['div',{class:'app'},'item']),虛擬DOM核心之一是diff算法麻敌,diff算法的核心之一是同層對(duì)比栅炒,如圖:
如果在第一層div時(shí)就有出現(xiàn)區(qū)別,那么對(duì)比結(jié)束术羔,直接更新真實(shí)DOM中對(duì)應(yīng)的當(dāng)前節(jié)點(diǎn)赢赊,以此類推。级历。释移。
再說說key,假設(shè)我們?cè)趕tate中有一個(gè)列表[a,b,c],在遍歷渲染時(shí)用索引作為key,那么就是這樣:
a 0
b 1
c 2
如果我們執(zhí)行一個(gè)操作寥殖,點(diǎn)擊刪除數(shù)組中的a玩讳, 我們的列表就是[b,c],在遍歷渲染時(shí)仍然會(huì)用索引作為key,結(jié)果如下:
b 0
c 1
如圖 嚼贡,我們?nèi)绻挥盟饕秊閗ey , 程序能快速的對(duì)比出差異熏纯,反之也能對(duì)出差異,但是必須對(duì)比整個(gè)虛擬DOM粤策,
這樣豆巨,程序仍然能正常執(zhí)行,只不過大大消耗了新舊虛擬DOM的對(duì)比的性能掐场,并可能導(dǎo)致組件狀態(tài)問題往扔。