欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何正確理解vue中的key詳解

 更新時(shí)間:2019年11月02日 08:37:36   作者:趁你還年輕  
這篇文章主要給大家介紹了關(guān)于如何正確理解vue中key的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

就目前所了解的情況,key的作用有以下這些。

  • v-for遍歷時(shí),用id,uuid之類作為key,唯一標(biāo)識(shí)節(jié)點(diǎn)加速虛擬DOM渲染
  • 響應(yīng)式系統(tǒng)沒(méi)有監(jiān)聽(tīng)到的數(shù)據(jù),用+new Date()生成的時(shí)間戳作為key,手動(dòng)強(qiáng)制觸發(fā)重新渲染

場(chǎng)景一大同小異司空見(jiàn)慣,場(chǎng)景二是下面這樣的:

<div :key="rerender">
  <span>Hello Vue.js !</span>
  <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
</div>

refresh(){
  this.rerender = + new Date();
}

那么vue中key的相關(guān)知識(shí)點(diǎn)到底是怎樣的呢?

  • 官方API知識(shí)點(diǎn)
  • 上面2個(gè)使用場(chǎng)景背后的原理是什么?
  • 除key外,還有其它強(qiáng)制更新DOM的方法嗎?
  • 參考資料

官方API知識(shí)點(diǎn)

  • 在Vue.js中,key是6個(gè)特殊屬性key, ref, is, slot, slot-scope, scope其中之一。
  • key的值可以是number,也可以是string。
  • key主要作用于Vue的virtual DOM算法,在diff new nodes list和old nodes list時(shí),作為識(shí)別VNode的一個(gè)線索。
  • 如果不用key,Vue會(huì)用一種算法:最小化element的移動(dòng),并且會(huì)嘗試盡最大程度在同適當(dāng)?shù)牡胤綄?duì)相同類型的element,做patch或者reuse。
  • 如果使用了key,Vue會(huì)根據(jù)keys的順序記錄element,曾經(jīng)擁有了key的element如果不再出現(xiàn)的話,會(huì)被直接remove或者destoryed。
  • 擁有同一個(gè)parent的children必須有unique keys。重復(fù)的key的導(dǎo)致render error。

最常用的用法一:v-for

<ul>
  <li v-for="item in items" :key="item.id">...</li>
</ul>

最常用的用法二:強(qiáng)制替換element或者component

  • 觸發(fā)組件的lifecycle
  • 觸發(fā)transition
<transition>
 <span :key="text">{{ text }}</span>
</transition>

text發(fā)生變化時(shí),<span>會(huì)被replaced,而不會(huì)patched,因此transition會(huì)被觸發(fā)。

我的理解:

text變化時(shí),span的key發(fā)生了變化,也就是說(shuō)曾經(jīng)擁有了舊key的span不再出現(xiàn)了,當(dāng)擁有新值的text作為key時(shí),擁有了新key的span出現(xiàn)了,那么舊key span會(huì)被移除,舊transition也會(huì)移除,新key span觸發(fā)渲染,新transition觸發(fā)。

上面2個(gè)使用場(chǎng)景背后的原理是什么?

結(jié)合官方API的知識(shí)點(diǎn),現(xiàn)在再來(lái)回顧文章開(kāi)頭提出的場(chǎng)景。

場(chǎng)景一:v-for遍歷時(shí),用id,uuid之類作為key,唯一標(biāo)識(shí)節(jié)點(diǎn)加速虛擬DOM渲染

答案:

  • 如果不用key,Vue會(huì)用一種算法:最小化element的移動(dòng),并且會(huì)嘗試盡最大程度在同適當(dāng)?shù)牡胤綄?duì)相同類型的element,做patch或者reuse。
  • 如果使用了key,Vue會(huì)根據(jù)keys的順序記錄element,曾經(jīng)擁有了key的element如果不再出現(xiàn)的話,會(huì)被直接remove或者destoryed。

場(chǎng)景二:響應(yīng)式系統(tǒng)沒(méi)有監(jiān)聽(tīng)到的數(shù)據(jù),用+new Date()生成的時(shí)間戳作為key,手動(dòng)強(qiáng)制觸發(fā)重新渲染

<div :key="rerender">
  <span>Hello Vue.js !</span>
  <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent>
</div>

refresh(){
  this.rerender = + new Date();
}

答案:

  • 如果使用了key,Vue會(huì)根據(jù)keys的順序記錄element,曾經(jīng)擁有了key的element如果不再出現(xiàn)的話,會(huì)被直接remove或者destoryed。
  • refresh方法調(diào)用后,包含了span和complexComponent的div的key發(fā)生了變化,也就是說(shuō)曾經(jīng)擁有了舊key的div不再出現(xiàn)了,當(dāng)擁有新值的rerender作為key時(shí),擁有了新key的div出現(xiàn)了,那么舊key div會(huì)被移除,舊span和complexComponent也會(huì)移除,新key div觸發(fā)渲染,新span,帶著父組件新propObj和propArr的新complexComponent渲染。

思考:

  • 為什么要叫propObj和propArr?
  • 帶著父組件新propObj和propArr的新complexComponent渲染。 為什么要加粗?

由于Vue.js的obj和arr存在無(wú)法檢測(cè)到數(shù)據(jù)變化的情況,obj是屬性的新增和刪除(原因是新增和刪除都沒(méi)有觸發(fā)setter,watcher未告訴外界更新),arr則是數(shù)組內(nèi)元素重新賦值或者修改length屬性(原因是沒(méi)有使用改變數(shù)組本身的方法,沒(méi)有觸發(fā)數(shù)組原型鏈攔截器,watcher未告訴外界更新)。

所以!通過(guò)賦予新key的方式,移除舊key div,渲染新key div,propObj和propArr在complexComponent組件內(nèi)會(huì)重新觸發(fā)一次生命周期,做一次重新渲染。此時(shí)父組件的propObj和propArr js變量其實(shí)已經(jīng)獲取到新值了,只是沒(méi)有觸發(fā)DOM也好,VNode也好的重新渲染。需要通過(guò)刷新key去force update,說(shuō)到forceUpdate,可以通過(guò)$forceUpdate()去手動(dòng)強(qiáng)制更新DOM。

除key外,還有其它強(qiáng)制更新DOM的方法嗎?

場(chǎng)景:父組件修改傳遞給子組件的數(shù)據(jù),數(shù)組數(shù)據(jù)的更新沒(méi)有按照this.$set去更新。該怎么辦?

this.productImages.forEach((product) => {
 if (product.productId in this.productsState) {
  product.status = this.productsState[product.productId];
 }
});

不使用this.$set去賦值數(shù)據(jù)的不能rerender的原因是什么?

在Vue.js中,對(duì)Array的變化偵測(cè)是通過(guò)攔截原型的方式實(shí)現(xiàn)的。也就通過(guò)對(duì)push,pop,shift,unshift,splice,sort,reverse,fill,copyWithin去改變數(shù)組自身內(nèi)容的方法做攔截,從而響應(yīng)。而product.status = this.productsState[product.productId];沒(méi)有觸發(fā)任何改變數(shù)組自身的被監(jiān)聽(tīng)的方法,因此不會(huì)rerender。

  • 刷新組件的key
  • $forceUpdate方法

刷新組件的key

1.這個(gè)key加在什么地方比較好?

加在this.productImages的父元素上就好。

若不涉及數(shù)據(jù)傳遞,也可以直接加在需要更新的element上。

2.用什么做key值?

現(xiàn)在是粗暴的+new Date()時(shí)間戳做key值的。

也可以用雙向綁定的值作為key值,保證新舊key值不同就行。

3.key的原理是什么?

vue.js的虛擬DOM算法,在更新vNode時(shí),需要從舊vNode列表中查找與新vNode節(jié)點(diǎn)相同的vNode進(jìn)行更新,如果這個(gè)過(guò)程設(shè)置了屬性key,過(guò)程就會(huì)快很多。

其他具體見(jiàn)上文。

$forceUpdate方法

只能在父組件調(diào)用這個(gè)方法,手動(dòng)通知vue實(shí)例重新渲染。

// $forceUpdate源碼
Vue.prototype.$forceUpdate = function () {
 const vm: Component = this
 if (vm._watcher) {
  vm._watcher.update()
 }
}
// update源碼
/**
 * Subscriber interface.
 * Will be called when a dependency changes.
 */
update () {
 /* istanbul ignore else */
 if (this.lazy) {
  this.dirty = true
 } else if (this.sync) {
  this.run()
 } else {
  queueWatcher(this)
 }
}

1.$forceUpdate可以更新的原理分析

product.status = this.productsState[product.productId];以后,其實(shí)此時(shí)dep已經(jīng)發(fā)生變化了,但是Vue.js數(shù)組響應(yīng)式的實(shí)現(xiàn)由于是攔截原型鏈方法的方式,沒(méi)有檢測(cè)到這個(gè)變化,所以不會(huì)自動(dòng)rerender,沒(méi)有觸發(fā)update。因此我們通過(guò)$forceUpdate的方式,調(diào)用包含dep的watcher上的update方法,從而做到rerender。

2.可以在子組件監(jiān)聽(tīng)事件,父組件發(fā)送事件然后只刷新子組件嗎?

不可以。

因?yàn)閐ep是父組件的watcher和dep,并不是子組件,是父組件的this.productImages沒(méi)有被檢測(cè)到并實(shí)時(shí)更新,并不是子組件的問(wèn)題。

參考資料

https://vuejs.org/v2/api/#key
https://vuejs.org/v2/api/#vm-...
https://vuejs.org/v2/guide/co...

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Vue+Vite項(xiàng)目初建(axios+Unocss+iconify)的實(shí)現(xiàn)

    Vue+Vite項(xiàng)目初建(axios+Unocss+iconify)的實(shí)現(xiàn)

    一個(gè)好的項(xiàng)目開(kāi)始搭建總是需要配置許多初始化配置,本文就來(lái)介紹一下Vue+Vite項(xiàng)目初建(axios+Unocss+iconify)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的全過(guò)程

    VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的全過(guò)程

    這篇文章主要給大家介紹了關(guān)于VUE+Canvas實(shí)現(xiàn)簡(jiǎn)單五子棋游戲的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • vue 實(shí)現(xiàn)購(gòu)物車總價(jià)計(jì)算

    vue 實(shí)現(xiàn)購(gòu)物車總價(jià)計(jì)算

    今天小編就為大家分享一篇vue 實(shí)現(xiàn)購(gòu)物車總價(jià)計(jì)算,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • vue-cli3.X快速創(chuàng)建項(xiàng)目的方法步驟

    vue-cli3.X快速創(chuàng)建項(xiàng)目的方法步驟

    這篇文章主要介紹了vue-cli3.X快速創(chuàng)建項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 解決vue attr取不到屬性值的問(wèn)題

    解決vue attr取不到屬性值的問(wèn)題

    今天小編就為大家分享一篇解決vue attr取不到屬性值的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • vue項(xiàng)目中如何添加枚舉

    vue項(xiàng)目中如何添加枚舉

    這篇文章主要介紹了vue項(xiàng)目中如何添加枚舉,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue中輕量級(jí)模糊查詢fuse.js使用方法步驟

    vue中輕量級(jí)模糊查詢fuse.js使用方法步驟

    這篇文章主要給大家介紹了關(guān)于vue中輕量級(jí)模糊查詢fuse.js使用方法的相關(guān)資料,Fuse.js是一個(gè)功能強(qiáng)大、輕量級(jí)的模糊搜索庫(kù),通過(guò)提供簡(jiǎn)單的?api?調(diào)用,達(dá)到強(qiáng)大的模糊搜索效果,需要的朋友可以參考下
    2024-01-01
  • 詳解vue 圖片上傳功能

    詳解vue 圖片上傳功能

    這篇文章主要介紹了vue 圖片上傳功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 如何使用Vue做個(gè)簡(jiǎn)單的比較兩個(gè)數(shù)字大小頁(yè)面

    如何使用Vue做個(gè)簡(jiǎn)單的比較兩個(gè)數(shù)字大小頁(yè)面

    這篇文章主要給大家介紹了關(guān)于如何使用Vue做個(gè)簡(jiǎn)單的比較兩個(gè)數(shù)字大小頁(yè)面的相關(guān)資料,實(shí)現(xiàn)一個(gè)比較兩個(gè)數(shù)字大小的頁(yè)面,練習(xí)Vue實(shí)例的創(chuàng)建、數(shù)據(jù)綁定和事件監(jiān)聽(tīng)方法,需要的朋友可以參考下
    2023-10-10
  • Vue?項(xiàng)目性能優(yōu)化方案分享

    Vue?項(xiàng)目性能優(yōu)化方案分享

    本文是作者通過(guò)實(shí)際項(xiàng)目的優(yōu)化實(shí)踐進(jìn)行總結(jié)而來(lái),希望讀者讀完本文,有一定的啟發(fā)思考,從而對(duì)自己的項(xiàng)目進(jìn)行優(yōu)化起到幫助
    2022-08-08

最新評(píng)論