中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

崇文網(wǎng)站建設(shè)北京網(wǎng)站優(yōu)化步驟

崇文網(wǎng)站建設(shè),北京網(wǎng)站優(yōu)化步驟,農(nóng)業(yè)門戶網(wǎng)站開發(fā),網(wǎng)站排名消失答題思路: nextTick 是做什么的?為什么需要它?開發(fā)時什么時候使用?介紹一下如何使用nextTick原理解讀,結(jié)合異步更新和nextTick生效方式 1. nextTick是做什么的? nextTick是等待下一次DOM更新刷新的工具方法…

答題思路:

  1. nextTick 是做什么的?
  2. 為什么需要它?
  3. 開發(fā)時什么時候使用?
  4. 介紹一下如何使用nextTick
  5. 原理解讀,結(jié)合異步更新和nextTick生效方式

1. nextTick是做什么的?

nextTick是等待下一次DOM更新刷新的工具方法。

<script>
import { nextTick } from 'vue'export default {data() {return {count: 0}},methods: {async increment() {this.count++// DOM 還未更新console.log(document.getElementById('counter').textContent) // 0await nextTick()// DOM 此時已經(jīng)更新console.log(document.getElementById('counter').textContent) // 1}}
}
</script><template><button id="counter" @click="increment">{{ count }}</button>
</template>

2. 為什么需要它?

Vue 有個異步更新策略,意思是如果數(shù)據(jù)變化,Vue不會立刻更新DOM,而是開啟一個隊(duì)列,把組件更新函數(shù)保存在隊(duì)列中,在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更會異步的批量更新。這一策略導(dǎo)致我們對數(shù)據(jù)的修改不會立刻體現(xiàn)在DOM上,此時如果想要獲取更新后的DOM狀態(tài),就需要使用nextTick。

3. 開發(fā)時什么時候使用?

4. 介紹一下如何使用nextTick

function nextTick(callback?: () => void): Promise<void>

所以我們只需要在傳入的回調(diào)函數(shù)中訪問最新DOM狀態(tài)即可,或者我們可以await nextTick()方法返回的Promise之后做這件事。

5. 原理解讀,結(jié)合異步更新和nextTick生效方式

在Vue內(nèi)部,nextTick之所以能夠讓我們看到DOM更新后的結(jié)果,是因?yàn)槲覀儌魅氲腸allback會被添加到列隊(duì)刷新函數(shù)(flushSchedulerQueue)的后面,這樣等隊(duì)列內(nèi)部的更新函數(shù)都執(zhí)行完畢,所有DOM操作也就結(jié)束了,callback自然能夠獲取到最新的DOM值。

將傳入的回調(diào)函數(shù)包裝成異步任務(wù),異步任務(wù)又分微任務(wù)和宏任務(wù),為了盡快執(zhí)行所以優(yōu)先選擇微任務(wù);

nextTick 提供了四種異步方法 Promise.then、MutationObserver、setImmediate、setTimeout(fn,0)

  • vue2

出于兼容性考慮,依次判斷瀏覽器是否支持,選擇使用對應(yīng)api
在這里插入圖片描述
優(yōu)先選擇微任務(wù),如果微任務(wù)都不支持,則選擇宏任務(wù)

  • vue3

拋棄了兼容性,直接使用Promise,來實(shí)現(xiàn)nextTick


由nextTick的源碼可以看出,nextTick本質(zhì)就是創(chuàng)建了一個微任務(wù)(不考慮setTimeout),將其回調(diào)推入微任務(wù)隊(duì)列。vue中一個事件循環(huán)中的所有dom更新操作也是一個微任務(wù),兩者屬于同一優(yōu)先級,執(zhí)行先后只于入隊(duì)的先后有關(guān),換句話說,如果你先寫了nextTick,再寫賦值語句(在此之前沒有觸發(fā)dom更新的操作),那在nextTick中獲取的可就不是更新后的dom了

<template><div class="demo"><p class="name">{{ name }}</p><button @click="modify">修改</button></div>
</template>
<script lang="ts" setup>
const name = ref("111");const modify = () => {name.value = "222"; // 關(guān)鍵的賦值語句,如果注釋掉,結(jié)果就大不一樣了nextTick(() => {const text = document.querySelector<HTMLElement>(".name").innerText;console.log(text);});name.value = "333";
};
</script>

如上代碼,如果注釋掉name.value = “2222”,雖然nextTick語句下面也有賦值操作:name.value = “3333”;,但由于nextTick先進(jìn)入微任務(wù)隊(duì)列,所以回調(diào)先于dom更新執(zhí)行,所以是獲取的dom仍舊是舊的更新前的dom
在這里插入圖片描述

  • 源碼補(bǔ)充
import { noop } from 'shared/util'
import { handleError } from './error'
import { isIE, isIOS, isNative } from './env'//  上面三行與核心代碼關(guān)系不大,了解即可
//  noop 表示一個無操作空函數(shù),用作函數(shù)默認(rèn)值,防止傳入 undefined 導(dǎo)致報錯
//  handleError 錯誤處理函數(shù)
//  isIE, isIOS, isNative 環(huán)境判斷函數(shù),
//  isNative 判斷某個屬性或方法是否原生支持,如果不支持或通過第三方實(shí)現(xiàn)支持都會返回 falseexport let isUsingMicroTask = false     // 標(biāo)記 nextTick 最終是否以微任務(wù)執(zhí)行const callbacks = []     // 存放調(diào)用 nextTick 時傳入的回調(diào)函數(shù)
let pending = false     // 標(biāo)記是否已經(jīng)向任務(wù)隊(duì)列中添加了一個任務(wù),如果已經(jīng)添加了就不能再添加了// 當(dāng)向任務(wù)隊(duì)列中添加了任務(wù)時,將 pending 置為 true,當(dāng)任務(wù)被執(zhí)行時將 pending 置為 false// // 聲明 nextTick 函數(shù),接收一個回調(diào)函數(shù)和一個執(zhí)行上下文作為參數(shù)
// 回調(diào)的 this 自動綁定到調(diào)用它的實(shí)例上
export function nextTick(cb?: Function, ctx?: Object) {let _resolve// 將傳入的回調(diào)函數(shù)存放到數(shù)組中,后面會遍歷執(zhí)行其中的回調(diào)callbacks.push(() => {if (cb) {   // 對傳入的回調(diào)進(jìn)行 try catch 錯誤捕獲try {cb.call(ctx)} catch (e) {    // 進(jìn)行統(tǒng)一的錯誤處理handleError(e, ctx, 'nextTick')}} else if (_resolve) {_resolve(ctx)}})// 如果當(dāng)前沒有在 pending 的回調(diào),// 就執(zhí)行 timeFunc 函數(shù)選擇當(dāng)前環(huán)境優(yōu)先支持的異步方法if (!pending) {pending = truetimerFunc()}// 如果沒有傳入回調(diào),并且當(dāng)前環(huán)境支持 promise,就返回一個 promise// 在返回的這個 promise.then 中 DOM 已經(jīng)更新好了,if (!cb && typeof Promise !== 'undefined') {return new Promise(resolve => {_resolve = resolve})}
}// 判斷當(dāng)前環(huán)境優(yōu)先支持的異步方法,優(yōu)先選擇微任務(wù)
// 優(yōu)先級:Promise---> MutationObserver---> setImmediate---> setTimeout
// setTimeout 可能產(chǎn)生一個 4ms 的延遲,而 setImmediate 會在主線程執(zhí)行完后立刻執(zhí)行
// setImmediate 在 IE10 和 node 中支持// 當(dāng)在同一輪事件循環(huán)中多次調(diào)用 nextTick 時 ,timerFunc 只會執(zhí)行一次let timerFunc   
// 判斷當(dāng)前環(huán)境是否原生支持 promise
if (typeof Promise !== 'undefined' && isNative(Promise)) {  // 支持 promiseconst p = Promise.resolve()timerFunc = () => {// 用 promise.then 把 flushCallbacks 函數(shù)包裹成一個異步微任務(wù)p.then(flushCallbacks)if (isIOS) setTimeout(noop)// 這里的 setTimeout 是用來強(qiáng)制刷新微任務(wù)隊(duì)列的// 因?yàn)樵?ios 下 promise.then 后面沒有宏任務(wù)的話,微任務(wù)隊(duì)列不會刷新}// 標(biāo)記當(dāng)前 nextTick 使用的微任務(wù)isUsingMicroTask = true// 如果不支持 promise,就判斷是否支持 MutationObserver// 不是IE環(huán)境,并且原生支持 MutationObserver,那也是一個微任務(wù)
} else if (!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) ||MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {let counter = 1// new 一個 MutationObserver 類const observer = new MutationObserver(flushCallbacks) // 創(chuàng)建一個文本節(jié)點(diǎn)const textNode = document.createTextNode(String(counter))   // 監(jiān)聽這個文本節(jié)點(diǎn),當(dāng)數(shù)據(jù)發(fā)生變化就執(zhí)行 flushCallbacks observer.observe(textNode, { characterData: true })timerFunc = () => {counter = (counter + 1) % 2textNode.data = String(counter)  // 數(shù)據(jù)更新}isUsingMicroTask = true    // 標(biāo)記當(dāng)前 nextTick 使用的微任務(wù)// 判斷當(dāng)前環(huán)境是否原生支持 setImmediate
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {timerFunc = () => { setImmediate(flushCallbacks)  }
} else {// 以上三種都不支持就選擇 setTimeouttimerFunc = () => { setTimeout(flushCallbacks, 0) }
}// 如果多次調(diào)用 nextTick,會依次執(zhí)行上面的方法,將 nextTick 的回調(diào)放在 callbacks 數(shù)組中
// 最后通過 flushCallbacks 函數(shù)遍歷 callbacks 數(shù)組的拷貝并執(zhí)行其中的回調(diào)
function flushCallbacks() {pending = false    const copies = callbacks.slice(0)    // 拷貝一份 callbackscallbacks.length = 0    // 清空 callbacksfor (let i = 0; i < copies.length; i++) {    // 遍歷執(zhí)行傳入的回調(diào)copies[i]()}
}// 為什么要拷貝一份 callbacks// 用 callbacks.slice(0) 將 callbacks 拷貝出來一份,
// 是因?yàn)榭紤]到在 nextTick 回調(diào)中可能還會調(diào)用 nextTick 的情況,
// 如果在 nextTick 回調(diào)中又調(diào)用了一次 nextTick,則又會向 callbacks 中添加回調(diào),
// 而 nextTick 回調(diào)中的 nextTick 應(yīng)該放在下一輪執(zhí)行,
// 否則就可能出現(xiàn)一直循環(huán)的情況,
// 所以需要將 callbacks 復(fù)制一份出來然后清空,再遍歷備份列表執(zhí)行回調(diào)
http://www.risenshineclean.com/news/40575.html

相關(guān)文章:

  • 網(wǎng)站空間流量西安競價托管
  • 線上營銷的優(yōu)勢和劣勢上海有哪些優(yōu)化網(wǎng)站推廣公司
  • 網(wǎng)站域名查詢官網(wǎng)網(wǎng)絡(luò)平臺
  • php網(wǎng)站開發(fā)視頻教程下載石家莊郵電職業(yè)技術(shù)學(xué)院
  • 用網(wǎng)站建設(shè)費(fèi)用南安網(wǎng)站建設(shè)
  • 浦東新區(qū)網(wǎng)站優(yōu)化公司關(guān)鍵詞推廣優(yōu)化排名如何
  • 做網(wǎng)站怎么備案谷歌官方網(wǎng)站登錄入口
  • 有沒有教做健身餐的網(wǎng)站搜索引擎優(yōu)化的主要手段
  • 網(wǎng)站橫幅廣告怎么做網(wǎng)站建設(shè)軟件
  • 坦洲網(wǎng)站建設(shè)公司哪家好拉新app渠道
  • 澳門建設(shè)銀行官方網(wǎng)站湖南優(yōu)化推廣
  • 公安網(wǎng)站備案服務(wù)類型萬江專業(yè)網(wǎng)站快速排名
  • 網(wǎng)站備案用座機(jī)租用重慶百度總代理
  • 企業(yè)網(wǎng)站模板優(yōu)化寧波seo排名外包公司
  • 北京網(wǎng)站備案號qq空間刷贊網(wǎng)站推廣
  • 疫情防控最新消息數(shù)據(jù)網(wǎng)站怎么優(yōu)化
  • 鎮(zhèn)江網(wǎng)站建設(shè)遠(yuǎn)航科技網(wǎng)站seo推廣營銷
  • 網(wǎng)站建設(shè)公司特色武漢seo人才
  • 新網(wǎng)站百度收錄北京疫情又嚴(yán)重了
  • 做二手衣服的網(wǎng)站有哪些關(guān)鍵詞歌詞圖片
  • wordpress 微信掃碼seo排名優(yōu)化推廣報價
  • 十大永久免費(fèi)污染軟件東莞seo搜索
  • 建設(shè)銀行的投訴網(wǎng)站推廣文案
  • 設(shè)計師個人網(wǎng)站網(wǎng)絡(luò)推廣渠道公司
  • 365元做網(wǎng)站網(wǎng)絡(luò)營銷的發(fā)展趨勢
  • 代做安裝預(yù)算的網(wǎng)站青島網(wǎng)站建設(shè)
  • 怎么自己的電腦做網(wǎng)站服務(wù)器百度廣告代理商
  • 網(wǎng)站運(yùn)營推廣方案云南百度公司
  • 網(wǎng)站ico圖標(biāo) 代碼搜索引擎排名中國
  • 上的網(wǎng)站app上海百度公司總部