最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue手寫實(shí)現(xiàn)異步更新詳解

 更新時(shí)間:2022年08月15日 11:05:22   作者:夏日  
這篇文章主要介紹了Vue手寫實(shí)現(xiàn)異步更新詳解,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,希望對(duì)你的學(xué)習(xí)有所幫助

前言:

本文將詳細(xì)講解具體的更新過程,并手寫實(shí)現(xiàn)Vue的異步更新邏輯相關(guān)代碼。

收集去重后的watcher進(jìn)行更新

這里先回顧一下依賴收集的相關(guān)知識(shí):

  • 頁面首次掛載,會(huì)從vm實(shí)例上獲取data中的值,從而調(diào)用屬性的get方法來收集watcher
  • 當(dāng)vm實(shí)例上的屬性更新它的值時(shí),會(huì)執(zhí)行收集到的watcherupdate方法

看下之前完成的代碼:

class Watcher {
  // some code ...
  update () {
    // 直接執(zhí)行更新操作
    this.get()
  }
}

那么watcherupdate到底應(yīng)該如何被執(zhí)行呢?這就是本文的重點(diǎn)。

watcher的更新操作主要分為如下倆步:

  • watcher去重后放到隊(duì)列中
  • 在異步任務(wù)中執(zhí)行存放的所有watcherrun方法

代碼如下:

class Watcher {
  // some code
  update () {
    queueWatcher(this);
  }

  run () {
    this.get();
  }
}

export default Watcher;

let queue = [];
let has = {}; // 使用對(duì)象來保存id,進(jìn)行去重操作
let pending = false; // 如果異步隊(duì)列正在執(zhí)行,將不會(huì)再次執(zhí)行

function flushSchedulerQueue () {
  queue.forEach(watcher => {
    watcher.run();
    if (watcher.options.render) { // 在更新之后執(zhí)行對(duì)應(yīng)的回調(diào): 這里是updated鉤子函數(shù)
      watcher.cb();
    }
  });
  // 執(zhí)行完成后清空隊(duì)列
  queue = [];
  has = {};
  pending = false;
}

function queueWatcher (watcher) {
  const id = watcher.id;
  if (!has[id]) {
    queue.push(watcher);
    has[id] = true;
    if (!pending) {
      pending = true;
      // 異步執(zhí)行watcher的更新方法
      setTimeout(flushSchedulerQueue)
    }
  }
}

此時(shí)已經(jīng)實(shí)現(xiàn)了視圖的異步更新,但是Vue還為用戶提供而了$nextTick方法,讓用戶可以在DOM更新之后做些事情。即$nextTick中的方法會(huì)在flushSchedulerQueue 執(zhí)行后才能執(zhí)行,下面就來看下$nextTick和視圖更新之間的邏輯。

實(shí)現(xiàn)nextTick方法

queueWatcher中其實(shí)并不是直接調(diào)用setTimeout來進(jìn)行視圖更新的,而是會(huì)調(diào)用內(nèi)部的nextTick方法。為用戶提供的$nextTick方法,也會(huì)調(diào)用nextTick方法。

該方法實(shí)現(xiàn)如下:

let callbacks = [];
let pending = false;

function flushCallbacks () {
  callbacks.forEach(cb => cb());
  callbacks = [];
  pending = false;
}

export function nextTick (cb) {
  callbacks.push(cb);
  if (!pending) {
    pending = true;
    timerFunc();
  }
}

nextTick會(huì)接收一個(gè)回調(diào)函數(shù),并將回調(diào)函數(shù)放到callbacks數(shù)組中,之后會(huì)通過timerFunc來異步執(zhí)行callbacks中的每一個(gè)函數(shù):

let timerFunc;
if (Promise) {
  timerFunc = function () {
    return Promise.resolve().then(flushCallbacks);
  };
} else if (MutationObserver) {
  timerFunc = function () {
    const textNode = document.createTextNode('1');
    const observer = new MutationObserver(() => {
      flushCallbacks();
      observer.disconnect();
    });
    const observe = observer.observe(textNode, { characterData: true });
    textNode.textContent = '2';
  };
} else if (setImmediate) {
  timerFunc = function () {
    setImmediate(flushCallbacks);
  };
} else {
  timerFunc = function () {
    setTimeout(flushCallbacks);
  };
}

timerFunc對(duì)異步API進(jìn)行了兼容處理,分別會(huì)先嘗試使用微任務(wù)Promise.then、MutationObserver、setImmediate ,如果這些API瀏覽器都不支持的話,那么會(huì)使用宏任務(wù)setTimeout。

queueWatcher里我們將flushSchedulerQueue作為參數(shù)執(zhí)行nextTick

function queueWatcher (watcher) {
  const id = watcher.id;
  if (!has[id]) {
    queue.push(watcher);
    has[id] = true;
    if (!pending) {
      pending = true;
      nextTick(flushSchedulerQueue);
    }
  }
}

Vue原型上,也要增加用戶可以通過實(shí)例來調(diào)用的$nextTick方法,其內(nèi)部調(diào)用nextTick

Vue.prototype.$nextTick = function (cb) {
  nextTick(cb);
};

$nextTick會(huì)將用戶傳入的回調(diào)函數(shù)也放到callbacks中,通過異步API來執(zhí)行。

測(cè)試demo詳解

上面已經(jīng)講解了視圖更新和$nextTick的實(shí)現(xiàn)代碼,接下來寫一個(gè)demo來實(shí)踐一下。

下面是實(shí)際開發(fā)中可能會(huì)用到的一段代碼:

<div id="app">{{name}}</div>
<script>
  const vm = new Vue({
    el: '#app',
    data () {
      return {
        name: 'zs'
      };
    }
  });
  vm.name = 'ls';
  console.log('$el', vm.$el);
  vm.$nextTick(() => {
    console.log('next tick $el', vm.$el);
  });
</script>

其輸出結(jié)果如下:

在了解了$nextTick的具體實(shí)現(xiàn)后,我們?cè)敿?xì)分析下代碼的執(zhí)行流程:

  • 在修改值之后,我們將要更新的watcher隊(duì)列放到了flushSchedulerQueue函數(shù)中來執(zhí)行
  • nextTickflushSchedulerQueue放到了callbacks中,通過異步任務(wù)來執(zhí)行flushCallbacks
  • 由于異步任務(wù)要等到主線程中的代碼執(zhí)行完畢后才會(huì)執(zhí)行,所以此時(shí)先打印vm.$el,視圖尚未更新
  • 接下來會(huì)繼續(xù)執(zhí)行vm.$nextTick,將vm.$nextTick中的回調(diào)函數(shù)也放到了callbacks中,但是其位置在flushSchedulerQueue后邊
  • 主線程中的代碼執(zhí)行完畢,開始執(zhí)行異步任務(wù)flushCallbacks。首先執(zhí)行flushSchedulerQueue更新DOM,然后再執(zhí)行$nextTick中的回調(diào)函數(shù),此時(shí)回調(diào)函數(shù)中可以獲取到最新的DOM

到此這篇關(guān)于Vue手寫實(shí)現(xiàn)異步更新詳解的文章就介紹到這了,更多相關(guān)Vue異步更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue transx組件切換動(dòng)畫庫示例詳解

    Vue transx組件切換動(dòng)畫庫示例詳解

    這篇文章主要為大家介紹了Vue transx組件切換動(dòng)畫庫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Vue3配置代理后頁面500/404問題

    Vue3配置代理后頁面500/404問題

    這篇文章主要介紹了Vue3配置代理后頁面500/404問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • vuex中g(shù)etters的基本用法解讀

    vuex中g(shù)etters的基本用法解讀

    這篇文章主要介紹了vuex中g(shù)etters的基本用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 關(guān)于vue利用postcss-pxtorem進(jìn)行移動(dòng)端適配的問題

    關(guān)于vue利用postcss-pxtorem進(jìn)行移動(dòng)端適配的問題

    這篇文章主要介紹了關(guān)于vue利用postcss-pxtorem進(jìn)行移動(dòng)端適配的問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Vue 不定高展開動(dòng)效原理詳解

    Vue 不定高展開動(dòng)效原理詳解

    本文主要介紹了Vue不定高展開動(dòng)效原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Vue3中事件總線mitt的使用方式

    Vue3中事件總線mitt的使用方式

    mitt又稱事務(wù)總線,是第三方插件,這篇文章主要為大家詳細(xì)介紹了Vue3中事件總線mitt的使用方式,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • Vue3 去除 vue warn 及生產(chǎn)環(huán)境去除console.log的方法

    Vue3 去除 vue warn 及生產(chǎn)環(huán)境去除console.log的方法

    這篇文章主要介紹了Vue3 去除 vue warn 及生產(chǎn)環(huán)境去除console.log的方法,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Vue.js仿微信聊天窗口展示組件功能

    Vue.js仿微信聊天窗口展示組件功能

    這篇文章主要介紹了Vue.js仿微信聊天窗口展示組件功能,需要的朋友可以參考下
    2017-08-08
  • Vue3中pinia用法示例

    Vue3中pinia用法示例

    這篇文章主要介紹了Vue3中使用pinia,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07
  • vue 自定義 select內(nèi)置組件

    vue 自定義 select內(nèi)置組件

    這篇文章主要介紹了vue 自定義內(nèi)置組件 select的相關(guān)知識(shí),整合了第三方j(luò)query 插件select2,具體實(shí)例代碼大家參考下本文
    2018-04-04

最新評(píng)論

上林县| 红安县| 土默特右旗| 庐江县| 乐山市| 嘉祥县| 肃宁县| 深水埗区| 旅游| 织金县| 桓台县| 临潭县| 西平县| 塔城市| 霍山县| 九寨沟县| 桐乡市| 晴隆县| 新闻| 辉县市| 永靖县| 虎林市| 永新县| 什邡市| 阳高县| 郎溪县| 天全县| 正宁县| 乐陵市| 榆中县| 页游| 曲周县| 托克托县| 青田县| 海盐县| 肥东县| 道真| 灵武市| 会宁县| 东台市| 黎平县|