色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

解析$nextTick魔力,為啥大家都愛它?

京東云 ? 來源:京東保險 卓雅倩 ? 作者:京東保險 卓雅倩 ? 2024-12-17 10:02 ? 次閱讀

作者:京東保險 卓雅倩

1.為什么需要使用$nextTick?

首先我們來看看官方對于$nextTick的定義:

在下次 DOM 更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的 DOM。

由于vue的試圖渲染是異步的,生命周期的created()鉤子函數進行的DOM操作一定要放在Vue.nextTick()的回調函數中,原因是在created()鉤子函數執行的時候DOM其實并未進行渲染,而此時進行DOM操作是徒勞的,所以一定要將DOM操作的js代碼放到Vue.nextTick()的回調函數中。除了在created()鉤子函數中使用之外咱們還會遇到很多種需要使用到Vue.nextTick()的場景,如下所示:

咱們日常生活中常常會遇上上述場景,會有很多問題,就比如當我們點擊按鈕更新數據時候,如下代碼示例:

點擊顯示輸入框,并且獲取輸入框焦點

export default { data() { return { isShow: false } }, methods : { handleClick () { this.isShow = true this.$refs.input.focus() //控制欄會報錯,因為還沒有這個dom } } }

點擊控制欄顯示效果:控制欄報錯,提示沒有獲取到dom元素;

wKgZPGdg27GAAbCXAAH_Vfnf58U128.png

所以現在Vue.nextTick()派上了用場,Vue.nextTick() 方法的作用正是等待上一次事件循環執行完畢,并在下一次事件循環開始時再執行回調函數。這樣可以保證回調函數中的 DOM 操作已經被 Vue.js 進行過更新,從而避免了一些潛在的問題,如下代碼所示:

點擊顯示輸入框,并且獲取輸入框焦點

export default { data() { return { isShow: false } }, methods : { handleClick () { this.isShow = true this.$nextTick(()=>{ this.$refs.input.focus() }) } } }

加上this.$nextTick后就能夠使得輸入框獲取到焦點;

總而言之Vue.nextTick()就是下次 DOM 更新渲染后執行延遲回調函數。在日常開發中,我們在修改數據之后使用這個方法,就可以獲取更新后的 DOM的同時進行在對DOM進行相對應操作的 js代碼;

2.$nextTick如何實現的?

JS是單線程執行的,所有的同步任務都是在主線程上執行的,形成了一個執行棧,從上到下依次執行,異步代碼會放在任務隊列里面。

?同步任務

在主線程里執行,當瀏覽器第一遍過濾html文件的時候可以執行完;(在當前作用域直接執行的所有內容,包括執行的方法、new出來的對象)

?異步任務

耗費時間較長或者性能較差的,瀏覽器執行到這些的時候會將其丟到異步任務隊列中,不會立即執行

同時異步任務分為宏任務(如setTimeout、setInterval、postMessage、setImmediate等)和微任務(Promise、process.nextTick等),瀏覽器執行這兩種任務的優先級不同;會優先執行微任務隊列的代碼,微任務隊列清空之后再執行宏任務的隊列,這樣循環往復;

JS自上向下進行代碼的編譯執行,遇到同步代碼壓入JS執行棧執行后出棧,遇到異步代碼放入任務隊列,當JS執行棧清空,去執行異步隊列中的回調函數,先去執行微任務隊列,當微任務隊列清空后,去檢測執行宏任務隊列中的回調函數,直至所有棧和隊列清空

整體流程如下圖所示:

wKgZO2dg27KAOPNyAASDxoSgV6Q704.png

接下來讓我們看看nextTick的源碼~

vue將nextTick的源碼放在了vue/core/util/next-tick.js中。如下圖所示:

wKgZPGdg27OAKML3AAaeel8WjTw493.png

我們把這個文件拆成三個部分來看:

1.nextTick定義函數

我們將nextTick函數單獨拿出來,callbacks是一個回調隊列,其實調用nextTick就是往這個數組里面傳執行任務,callbacks新增回調函數之后執行timerFunc函數,pending是用來限制同一個事件循環內只能執行一次的pending鎖;

const callbacks = [] // 回調隊列 let pending = false // export function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { // cb 回調函數會經統一處理壓入 callbacks 數組 if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) // 執行異步延遲函數 timerFunc if (!pending) { pending = true timerFunc() } // $flow-disable-line // 當 nextTick 沒有傳入函數參數的時候,返回一個 Promise 化的調用 if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve }) } }

2.timerFunc函數做了四個判斷,先后嘗試當前環境是否能夠使用原生的Promise.then、MutationObserver和setImmediate,不斷的降級處理,如果以上三個都不支持,則最后就會直接使用setTimeOut,主要操作就是將flushCallbacks中的函數放入微任務或者宏任務,等待下一個事件循環開始執行;宏任務耗費的時間是大于微任務的,所以在瀏覽器支持的情況下,優先使用微任務。如果瀏覽器不支持微任務,使用宏任務;但是,各種宏任務之間也有效率的不同,需要根據瀏覽器的支持情況,使用不同的宏任務;

export let isUsingMicroTask = false let timerFunc if (typeof Promise !== 'undefined' && isNative(Promise)) { //是否支持Promise const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) if (isIOS) setTimeout(noop) } isUsingMicroTask = true } else if (!isIE && typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]' )) { //是否支持MutationObserver let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } isUsingMicroTask = true } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { timerFunc = () => { //是否支持setImmediate setImmediate(flushCallbacks) } } else { // Fallback to setTimeout. timerFunc = () => { //上面都不行,直接使用setTimeout setTimeout(flushCallbacks, 0) } }

3.flushCallbacks函數

flushCallbacks函數只有幾行,也很好理解,將pending鎖置為false,同時將callbacks數組復制一份之后再將callbacks置為空,接下來將復制出來的callbacks數組的每個函數依次進行執行,簡單來說它的主要作用就是用來執行callbacks中的回調函數;

function flushCallbacks () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() } }

值得注意的是,$nextTick 并不是一個真正意義上的微任務microtask,而是利用了事件循環機制來實現異步更新。因此,它的執行時機相對于微任務可能會有所延遲,但仍能保證在 DOM 更新后盡快執行回調函數。

總的來說,nextTick就是:

1.將傳入的回調函數放入callbacks數組等待執行,定義pending判斷鎖保證一個事件循環中只能調用一次timerFunc函數;

2.根據環境判斷使用異步方式,調用timerFunc函數調用flushCallbacks函數依次執行callbacks中的回調函數;

3.個人小結

nextTick可避免數據更新后導致DOM的數據不一致的問題,提供了更穩定的異步更新機制,解決了created鉤子函數DOM未渲染會造成的異步數據渲染問題,但如果過多的使用nextTick會導致事件循環中任務數量和回調函數增多,有可能出現可怕的回調地獄,導致性能下降,同時過度依賴nextTick也會降低代碼的可讀性,所以大家還是"按需加載"的好~

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • DOM
    DOM
    +關注

    關注

    0

    文章

    18

    瀏覽量

    9594
  • vue
    vue
    +關注

    關注

    0

    文章

    58

    瀏覽量

    7868
收藏 人收藏

    評論

    相關推薦

    AMOLED屏有什么魔力?華為、小米都愛

    越來越多的手機廠商在屏幕選擇上偏愛OLED,華為、OPPO、vivo、小米等都加入了AMOLED的陣營,這塊屏幕究竟存在什么樣的魔力,能夠吸引這么多廠商?
    發表于 08-24 09:45 ?2985次閱讀

    用proteus6.7仿真提示cannot find model file bldcm.mdf這是為啥??

    用proteus6.7仿真提示cannot find model file bldcm.mdf這是為啥,大神們幫我看看的,求解答的,求解決問題。。。。
    發表于 05-15 12:24

    魔力非凡——隆宇 黑魔力電源凈化器“魔力2500”

    我說他們推出了一款LY-6KW最新改良型,倍頻率高達2500倍,型號大致不變是LY-6KW-1,名字叫做魔力2500,說是音效十分出色,比我原來那臺要好得多,叫我一定要試一試,作個AB比較云云。有
    發表于 04-02 12:14

    模擬電路有什么魔力

    猜猜看是哪兩家半導體廠商?——的公司名稱以T開頭,過去主要做數字IC,如今卻認為模擬電子更精彩且更具報酬效益!對于半導體廠商來說,過去曾經是只要具備擴展數字晶體管的能力,即可提供一個看起來前景無限
    發表于 06-21 04:20

    智能魔鏡顯示屏是什么,究竟魔力何在

    隨著黑科技逐漸滲入到日常生活,人們對科技產品的審視標準日益嚴格,傳統鏡子主要功能是被人們用來整理儀容。然而隨著科學技術在各個領域中的普及化,鏡子的單一功能被改寫,曠世智能魔鏡顯示屏,究竟魔力何在
    發表于 09-02 16:31 ?819次閱讀

    搞嵌入式,為啥要有uboot?

    搞嵌入式的,為啥要有uboot?
    的頭像 發表于 02-05 12:00 ?3021次閱讀

    日本人都愛買什么手機?國產手機品牌為啥在日本就打不過當地品牌呢

    則是唯一一個亮眼的國際品牌。 所以,風靡全球的華為、小米等國產手機品牌,為啥在日本就打不過當地品牌呢?蘋果贏得市場的秘訣又是啥? 日本人都愛買什么手機? 在許多國人的印象中,日本人最喜歡用的就是翻蓋式的功能機,一群穿著校
    的頭像 發表于 12-11 17:44 ?1.4w次閱讀

    為什么單相電機要用電容啟動?

    為啥單相電機要用電容啟動呢?本文小編就來給大家解析一下。
    的頭像 發表于 12-14 21:24 ?1565次閱讀

    為啥單相電機要用電容啟動?

    為啥單相電機要用電容啟動呢?本文小編就來給大家解析一下。
    發表于 03-12 06:06 ?57次下載
    <b class='flag-5'>為啥</b>單相電機要用電容啟動?

    Gartner魔力象限報告中將IBM評為AI領導者

    IBM 在 Gartner 2021年“云 AI 開發者服務魔力象限“和“數據科學與機器學習平臺魔力象限”報告中均被評為領導者。 精彩提要 中國北京,2021年 3月 12日 —— IBM
    的頭像 發表于 03-19 09:47 ?1894次閱讀

    to B軟件為啥用戶體驗不好

    to B軟件為啥用戶體驗不好?我今天從機制根源層面給大家說說。否則大家還停留在UI、UE的認知層面上。(1)從甲方視角看to B軟件其實分為:高層決策軟件、中層管理軟件、基層業務操作軟件。...
    發表于 12-28 19:37 ?6次下載
    to B軟件<b class='flag-5'>為啥</b>用戶體驗不好

    從藍光到綠色魔力

    從藍光到綠色魔力
    發表于 11-02 08:16 ?0次下載
    從藍光到綠色<b class='flag-5'>魔力</b>

    國內唯一,華為再次入選2022 Gartner SIEM魔力象限

    2022年10月,業界知名分析機構Gartner公司發布2022年SIEM(Security Information and Event Management,安全信息和事件管理)魔力象限
    的頭像 發表于 11-16 19:35 ?748次閱讀

    高速信號為啥要走表層?

    高速信號為啥要走表層?
    的頭像 發表于 12-05 15:16 ?627次閱讀
    高速信號<b class='flag-5'>為啥</b>要走表層?

    被眾人吐槽的Keil,為啥還能挺到現在?

    這款工具相信大家都不陌生,一直被人吐槽很難用,但它為啥沒有被淘汰呢?一、Keil被吐槽的點Keil被大家吐槽最多的還是那千年不變的UI界面,其他很多IDE的界面都比較“現代化”,而K
    的頭像 發表于 04-18 08:10 ?1246次閱讀
    被眾人吐槽的Keil,<b class='flag-5'>為啥</b>還能挺到現在?
    主站蜘蛛池模板: 俄罗斯美女啪啪 | 午夜国产在线观看 | 果冻传媒视频在线播放 免费观看 | 久久九九免费 | 日本久久免费大片 | 国模精品一区二区三区视频 | 天美传媒在线观看完整高清 | 性欧美13处14处破 | 狼好色有你好看 | 国产特级毛片AAAAAAA高清 | 久久成人免费观看草草影院 | 日本久久和电影 | 秋霞电影网伦大理电影在线观看 | 解开美女胸衣2破解版 | 一级毛片免费播放 | 亚洲精品视频在线播放 | 欧美成人国产 | 国产精品视频人人做人人爽 | 美女漏bb | 久久九九久精品国产尤物 | 国产精品无码无卡毛片不卡视 | 日韩精品久久日日躁夜夜躁影视 | 亚洲网站视频在线观看 | 很很射影院 | 中文字幕一区二区三区在线观看 | 欧美黑人巨大性极品hd欧 | 嫩草影院一区 | 男人扒开添女人下部口述 | 国产成人无码免费精品果冻传媒 | 国语自产拍大学生在线观看 | 暖暖的视频完整视频免费韩国 | 国产精品…在线观看 | 51无码人妻精品1国产 | 暖暖日本在线手机免费完整版 | 欧美在线亚洲综合国产人 | 亚洲第一色网 | 亚洲免费视频日本一区二区 | 翘臀少妇被扒开屁股日出水爆乳 | 蜜桃狠狠色伊人亚洲综合网站 | 少妇无套内谢久久久久 | 漂亮妈妈中文字幕版 |