国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

詳解從Vue.js源碼看異步更新DOM策略及nextTick

2024-05-06 15:25:48
字體:
來源:轉載
供稿:網友

寫在前面

因為對Vue.js很感興趣,而且平時工作的技術棧也是Vue.js,這幾個月花了些時間研究學習了一下Vue.js源碼,并做了總結與輸出。

文章的原地址:https://github.com/answershuto/learnVue。

在學習過程中,為Vue加上了中文的注釋https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以對其他想學習Vue源碼的小伙伴有所幫助。

可能會有理解存在偏差的地方,歡迎提issue指出,共同學習,共同進步。

操作DOM

在使用vue.js的時候,有時候因為一些特定的業務場景,不得不去操作DOM,比如這樣:

<template> <div> <div ref="test">{{test}}</div> <button @click="handleClick">tet</button> </div></template>
export default { data () {  return {   test: 'begin'  }; }, methods () {  handleClick () {   this.test = 'end';   console.log(this.$refs.test.innerText);//打印“begin”  } }}

打印的結果是begin,為什么我們明明已經將test設置成了“end”,獲取真實DOM節點的innerText卻沒有得到我們預期中的“end”,而是得到之前的值“begin”呢?

Watcher隊列

帶著疑問,我們找到了Vue.js源碼的Watch實現。當某個響應式數據發生變化的時候,它的setter函數會通知閉包中的Dep,Dep則會調用它管理的所有Watch對象。觸發Watch對象的update實現。我們來看一下update的實現。

update () { /* istanbul ignore else */ if (this.lazy) {  this.dirty = true } else if (this.sync) {  /*同步則執行run直接渲染視圖*/  this.run() } else {  /*異步推送到觀察者隊列中,下一個tick時調用。*/  queueWatcher(this) }}

我們發現Vue.js默認是使用異步執行DOM更新。

當異步執行update的時候,會調用queueWatcher函數。

 /*將一個觀察者對象push進觀察者隊列,在隊列中已經存在相同的id則該觀察者對象將被跳過,除非它是在隊列被刷新時推送*/export function queueWatcher (watcher: Watcher) { /*獲取watcher的id*/ const id = watcher.id /*檢驗id是否存在,已經存在則直接跳過,不存在則標記哈希表has,用于下次檢驗*/ if (has[id] == null) { has[id] = true if (!flushing) {  /*如果沒有flush掉,直接push到隊列中即可*/  queue.push(watcher) } else {  // if already flushing, splice the watcher based on its id  // if already past its id, it will be run next immediately.  let i = queue.length - 1  while (i >= 0 && queue[i].id > watcher.id) {  i--  }  queue.splice(Math.max(i, index) + 1, 0, watcher) } // queue the flush if (!waiting) {  waiting = true  nextTick(flushSchedulerQueue) } }}

查看queueWatcher的源碼我們發現,Watch對象并不是立即更新視圖,而是被push進了一個隊列queue,此時狀態處于waiting的狀態,這時候會繼續會有Watch對象被push進這個隊列queue,等待下一個tick時,這些Watch對象才會被遍歷取出,更新視圖。同時,id重復的Watcher不會被多次加入到queue中去,因為在最終渲染時,我們只需要關心數據的最終結果。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 津市市| 常德市| 贡觉县| 牟定县| 溆浦县| 高淳县| 治县。| 日土县| 霞浦县| 忻城县| 清原| 霍林郭勒市| 青神县| 民和| 吉安县| 永城市| 福安市| 霍林郭勒市| 登封市| 陇南市| 临颍县| 德阳市| 平安县| 古蔺县| 开远市| 垣曲县| 虎林市| 九江市| 驻马店市| 礼泉县| 定日县| 临武县| 铁力市| 体育| 康定县| 图片| 高淳县| 确山县| 博罗县| 确山县| 包头市|