1. 程式人生 > >【Vue原理】NextTick

【Vue原理】NextTick

寫文章不容易,點個讚唄兄弟 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳情,讓我們一起學習吧 研究基於 Vue版本 【2.5.17】

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧

【Vue原理】NextTick - 原始碼版 之 巨集微任務的抉擇

nextTick 已經寫了三篇文章啦,這是最後一篇原始碼版,沒看過的童鞋可以看看白話版簡單瞭解下拉

【Vue原理】NextTick - 白話版 簡單瞭解下NextTick

在前面的文章 NextTick-原始碼版之獨立自身

埋下過兩個問題

1、Vue 在哪裡使用到了 巨集任務和 微任務

2、Vue 為什麼需要 巨集任務 和微任務

今天的任務就是解決這兩個問題!!!

在這裡,大家肯定必須一定要了解了 巨集任務和 微任務的哈,這兩個東西不贅述了

首先,第一個問題就是巨集微任務的使用場景場景


巨集微任務的使用場景

1、Vue 一般情況下使用的是微任務

2、在繫結DOM 事件的時候,會使用巨集任務。

這麼講,有點籠統,準確地說,應該是

事件回撥執行過程中,在JS 主執行緒為空之後,非同步程式碼執行之前,所有通過 nextTick 註冊的非同步程式碼都是用巨集任務。

來看看繫結DOM 事件的原始碼

通過 addEventListener 給 DOM 繫結事件

function add$1(event, handler) {
    handler = withMacroTask(handler);
    target$1.addEventListener(event, handler);

}



function withMacroTask(fn) {    

    return fn._withTask || (fn._withTask = function() {

        useMacroTask = true;        

        var res = fn.apply(null, arguments);

        useMacroTask = false;        

        return res

    })
}

你看到了,把原先DOM 事件的回撥包裝了一遍,然後通過設定 useMacroTask 來控制註冊巨集任務

useMacroTask 沒見過,在 nextTick 獨立流程中已經講過了的

在呼叫 nextTick 的時候,正是通過這個變數來控制,此次非同步程式碼註冊的任務型別

Vue.nextTick =function (cb, ctx) {


    callbacks.push(function() {
        cb && cb.call(ctx);

    });    



    if (!pending) {

        pending = true;        

        if (useMacroTask) {

            macroTimerFunc();
        } else {
            microTimerFunc();
        }
    }
}

好多,現在我們來解決第二個問題!


為什麼需要巨集微任務

為什麼要特地在事件回撥執行期間 使用巨集任務啊,想了好好久啊,才腦抽想到去看了下 Vue 的註釋

大概意思是這樣

本來 Vue 是從來都使用微任務的,因為微任務的優先順序比較高,執行比較快。但是同時也是因為這樣導致了一個問題

什麼問題?

在連續事件發生的期間,微任務就已經執行了

就是

事件回撥執行完成之後,會馬上執行微任務

那麼連續多個事件回撥同時執行,就會導致連續多次執行微任務

如果連續多個事件回撥中,都有修改資料,如下

this.state = xxxxx

那麼很明顯,會導致頁面頻繁的更新,這顯然不是我們想要的結果

那到底什麼是連續的事件?

那就是冒泡!

我們來現場演示一下微任務下的冒泡事件

<div style="height:100px;width:100px;background:red">
  <div style="height:60px;width:60x;background:black">
    <div style="height:30px;width:30px;background:blue">
    </div>

  </div>

</div>
div1.onclick = function() {    

    console.log("div1");

    Promise.resolve().then(() = >{        

        console.log("promise1")

    })
}

div2.onclick = function() {    

    console.log("div2");    

    Promise.resolve().then(() = >{        

        console.log("promise2")

    })
}

div3.onclick = function() {    

    console.log("div3");    

    Promise.resolve().then(() = >{        

        console.log("promise3")

    })
}


公眾號

看到了嗎,promise 在一個事件回撥結束之後馬上就呼叫了

如果在 Vue 中的事件回撥中修改了資料 this.state = xxxxx

然後資料一更改,就會註冊微任務用於響應更新,然後事件結束之後,馬上執行微任務

如果三個事件回撥都有修改資料,那麼就會註冊三次,執行三次,就會更新三次

所以

尤大想到了一個方法,就是在事件回撥執行時,註冊的是巨集任務

巨集任務並不會在事件結束之後馬上呼叫

只會在連續事件結束之後,才呼叫,這就是我們想要的

所以你才能看到 使用 useMacroTask 來控制註冊的任務型別

現在我把上面的例子中的 promise 換成 setTimeout,重新點選一下

公眾號

但是!!

在 【Vue 2.6】 中,我們已經看不到 useMacroTask 的身影了,為什麼?

因為 Vue 又全部使用微任務了........ 天道輪迴.....

(其實並不是全部是微任務,相容寫法最後是 setTimeout)

你問,那冒泡又怎麼辦?

好吧,尤大想到了另一個辦法來解決冒泡的問題

就是判斷當時的 事件 target,來判斷是否執行事件回撥

也就間接解決了這個問題,看看新的繫結事件的原始碼

function add$1(name, handler) {
    handler = function(e) {        

        if (

            e.target === e.currentTarget ||

            e.target.ownerDocument !== document

        ) {  

          return  handler.apply(this, arguments)

        }
    };
    target$1.addEventListener(name, handler);
}

通過判斷 target 就解決了冒泡,但是這樣就不能用冒泡了好像??

也不知道有沒有什麼壞處,如果有的話,後面尤大肯定會更新的

相關推薦

Vue原理NextTick

寫文章不容易,點個讚唄兄弟 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳

Vue原理Watch

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Watch - 原始碼版 今天繼續探索 Watch 原始碼,廢話不多說了 帶著我的幾個疑問開始 1、什麼時候初始化 2、怎麼確定監聽哪些值 3、深度監聽怎麼回事 4、怎麼觸發我的函式 這些問題的答案會摻

Vue原理Props

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Props - 原始碼版 今天記錄 Props 原始碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做了詳細的文章,忘記了什麼的,回憶起來必然是很快的。 好的,回到正題,Props 請你

Vue原理Mixins

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Mixins - 原始碼版 今天探索的是 mixins 的原始碼,mixins 根據不同的選項型別會做不同的處理 篇幅會有些長,你知道的,有很多種選項型別的嘛,但不是很難。只是涉及原始碼難免會有些煩, 不過這篇文

Vue原理依賴更新

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】依賴更新 - 原始碼版 如果對依賴收集完全沒有概念的同學,可以先看我這篇白話版 響應式原理 - 白話版 我們已經講過了 依賴收集 【Vue原理】依賴收集 - 原始碼版之基本資料型別 【Vue

Vue原理VNode

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】VNode - 原始碼版 今天就來探索 VNode 的原始碼,VNode 是 Vue2 渲染機制中很重要的一部分,是深入Vue 必須瞭解的部分 我們以4個問題來開始我們的探索 1、vnode 是什麼及其作用

Vue原理Event

如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Event - 原始碼版 之 自定義事件 Vue 的自定義事件很簡單,就是使用 觀察者模式 進行事件的監聽和分發 Vue 封裝的這個觀察者模式,可以說是很完善了,這個可以獨立抽取出來的在其他專案中使用的程式碼,

Vue原理Render

寫文章不容易,點個讚唄兄弟 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳

Vue原理Diff

寫文章不容易,點個讚唄兄弟 <br> <br> 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,

vue.js入門

emp 寫到 logs 組件 images href one mooc 渲染 慕課網視頻學習筆記:http://www.imooc.com/learn/694 1.將html、js、css寫到一個後綴名.vue的文件中,區分這三種類型是通過<template>、

底層原理四位計算機的原理及其實現

一點 led燈 waiting lean div rm2 src and nvt 你是否想過,計算機為什麽會加減乘除?或者更直接一點,計算機的原理到底是什麽? Waitingforfriday有一篇詳細的教程,講解了如何自己動手,制作一臺四位計算機。從中可以看到,二進制、數

計算機原理程序執行過程

進程 cnblogs div 空間 時間片 chat 內存管理 tro alt 本章主要介紹程序執行過程中操作系統、CPU都幹了什麽 運行前 程序在運行前,只是在硬盤上待著,此時就是一堆二進制代碼而已,沒有任何作用。 程序只有進入了內存才能運行,但是要進入內存,則需要服從操

計算機原理CPU部分.md

工作 信號 通過 臃腫 流水線 處理 2.6 操作 ade 本文由CPU阿甘改編而得,主要講的是系統啟動和程序執行時CPU做的工作。 CPU的構成 中央處理器(CPU,Central Processing Unit)由運算器、控制器、Cache等。 控制器:主要是對指令進

組成原理第一章 計算機系統概述

表示 運算 傳遞 intro 指令 掌握 周期 style 主存 重點掌握:MAR和MDR的含義,主存容量大小、CPU執行時間的計算,性能指標CPI、MIPS、主頻等等。 1. 存儲單元:CPU訪問存儲器的基本單位,每個單元有一個地址。通常是字節大小的整數倍。 2. CPU

編譯原理c++實現自下而上語法分析器

不可 acm times style size PC -i 表達式 鏈接 寫在前面:本博客為本人原創,嚴禁任何形式的轉載!本博客只允許放在博客園(.cnblogs.com),如果您在其他網站看到這篇博文,請通過下面這個唯一的合法鏈接轉到原文! 本博客全網唯一合法URL:ht

計數原理UVA11538 Chess Queen

put typename return col nbsp 題意 putchar cst putc 傳送門 Description   給你一個n*m的棋盤,在棋盤上放置一黑一白兩個皇後,求兩個皇後能夠互相攻擊的方案個數 Input   多組數據,每組數據包括:

MongoDB 復制集 第 二 部 之選舉原理

command primary red and 優先權 mongo mongodb 主機 set 目錄: 1·復制與選舉的原理與驗證2·oplog 日誌調整3·配置復制集的優先級4·部署認證的復制5·總結 復制與選舉的原理: 上一篇文章搭建了多臺實例,部署成復制集,

Memcached 主主復制 + Keepalived 高可用架構附上原理

ima pki nag ali event 主服務器 figure tel outer 目錄: 1·Memcached 主主復制概念2·Memcached 高可用的實現3·案例部署4·總結 Memcached 主主復制概念 (1)主主復制概念: Memcached

Windows原理非同步IO-_APC(非同步過程呼叫)

// 同步IO的缺點是, 在讀寫檔案時, 如果檔案太大, 或者讀寫的時間太長, 就會在讀寫函式中 // 阻塞住. // 非同步IO解決了這個問題, 非同步IO讀寫檔案時, 檔案再大也不會阻塞住 // 但是非同步IO要完成這樣的特性是有一點付出的 // 非同步讀寫檔案後, 需要通過一些方式

Windows原理IO非同步-等待事件物件

/* 同步IO的缺點是, 在讀寫檔案時, 如果檔案太大, 或者讀寫的時間太長, 就會在讀寫函式中 阻塞住. 非同步IO解決了這個問題, 非同步IO讀寫檔案時, 檔案再大也不會阻塞住 但是非同步IO要完成這樣的特性是有一點付出的 非同步讀寫檔案後, 需要通過一些方式才能知道檔案讀寫(IO