就目前所了解的情況,key的作用有以下這些。
站在用戶的角度思考問題,與客戶深入溝通,找到臨武網(wǎng)站設(shè)計(jì)與臨武網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋臨武地區(qū)。
場(chǎng)景一大同小異司空見慣,場(chǎng)景二是下面這樣的:
Hello Vue.js !refresh(){ this.rerender = + new Date(); }
那么vue中key的相關(guān)知識(shí)點(diǎn)到底是怎樣的呢?
官方API知識(shí)點(diǎn)
最常用的用法一:v-for
最常用的用法二:強(qiáng)制替換element或者component
{{ text }}
text發(fā)生變化時(shí),會(huì)被replaced,而不會(huì)patched,因此transition會(huì)被觸發(fā)。
我的理解:
text變化時(shí),span的key發(fā)生了變化,也就是說曾經(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)在再來回顧文章開頭提出的場(chǎng)景。
場(chǎng)景一:v-for遍歷時(shí),用id,uuid之類作為key,唯一標(biāo)識(shí)節(jié)點(diǎn)加速虛擬DOM渲染
答案:
場(chǎng)景二:響應(yīng)式系統(tǒng)沒有監(jiān)聽到的數(shù)據(jù),用+new Date()生成的時(shí)間戳作為key,手動(dòng)強(qiáng)制觸發(fā)重新渲染
Hello Vue.js !refresh(){ this.rerender = + new Date(); }
答案:
思考:
由于Vue.js的obj和arr存在無法檢測(cè)到數(shù)據(jù)變化的情況,obj是屬性的新增和刪除(原因是新增和刪除都沒有觸發(fā)setter,watcher未告訴外界更新),arr則是數(shù)組內(nèi)元素重新賦值或者修改length屬性(原因是沒有使用改變數(shù)組本身的方法,沒有觸發(fā)數(shù)組原型鏈攔截器,watcher未告訴外界更新)。
所以!通過賦予新key的方式,移除舊key div,渲染新key div,propObj和propArr在complexComponent組件內(nèi)會(huì)重新觸發(fā)一次生命周期,做一次重新渲染。此時(shí)父組件的propObj和propArr js變量其實(shí)已經(jīng)獲取到新值了,只是沒有觸發(fā)DOM也好,VNode也好的重新渲染。需要通過刷新key去force update,說到forceUpdate,可以通過$forceUpdate()去手動(dòng)強(qiáng)制更新DOM。
除key外,還有其它強(qiáng)制更新DOM的方法嗎?
場(chǎng)景:父組件修改傳遞給子組件的數(shù)據(jù),數(shù)組數(shù)據(jù)的更新沒有按照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è)是通過攔截原型的方式實(shí)現(xiàn)的。也就通過對(duì)push,pop,shift,unshift,splice,sort,reverse,fill,copyWithin去改變數(shù)組自身內(nèi)容的方法做攔截,從而響應(yīng)。而product.status = this.productsState[product.productId];沒有觸發(fā)任何改變數(shù)組自身的被監(jiān)聽的方法,因此不會(huì)rerender。
刷新組件的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è)過程設(shè)置了屬性key,過程就會(huì)快很多。
其他具體見上文。
$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)由于是攔截原型鏈方法的方式,沒有檢測(cè)到這個(gè)變化,所以不會(huì)自動(dòng)rerender,沒有觸發(fā)update。因此我們通過$forceUpdate的方式,調(diào)用包含dep的watcher上的update方法,從而做到rerender。
2.可以在子組件監(jiān)聽事件,父組件發(fā)送事件然后只刷新子組件嗎?
不可以。
因?yàn)閐ep是父組件的watcher和dep,并不是子組件,是父組件的this.productImages沒有被檢測(cè)到并實(shí)時(shí)更新,并不是子組件的問題。
參考資料
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ì)創(chuàng)新互聯(lián)的支持。