這篇“Vue的this.$nextTick怎么使用”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“Vue的this.$nextTick怎么使用”文章吧。
成都創(chuàng)新互聯(lián)專注于企業(yè)網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站重做改版、三元網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5場(chǎng)景定制、商城網(wǎng)站定制開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為三元等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
nextTick:在下一次DOM更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法,獲取更新后的DOM。它有兩個(gè)參數(shù):第一個(gè)參數(shù)是
回調(diào)函數(shù)
,不傳時(shí)提供promise調(diào)用;第二個(gè)參數(shù)是執(zhí)行環(huán)境上下文
,不傳默認(rèn)是自動(dòng)綁定到調(diào)用它的實(shí)例上。
我們先看看nextTick究竟是個(gè)啥?
console.log(this.$nextTick);
// 控制臺(tái)打印
if(fn){
return nextTick(fn, this);
}
我們可以看出nextTick就是一個(gè)方法,方法有兩個(gè)參數(shù):fn和this,fn就是需要傳的回調(diào)函數(shù),this就是所說(shuō)的執(zhí)行環(huán)境上下文。那么問(wèn)題來(lái)了,在Vue中是如何實(shí)現(xiàn)在下一次DOM更新結(jié)束之后才會(huì)執(zhí)行延遲回調(diào)的?我們先看看下面的例子:
<div ref="test1">created:{{message}}</div>
// vue實(shí)例
data: {
message: "Hello World!",
},
created(){
this.message = '你好,世界!';
console.log(this.$refs.test1.innerText);// 報(bào)錯(cuò)
// TypeError: Cannot read properties of undefined (reading 'innerText')
this.$nextTick(()=>{
console.log('test1 nextTick:',this.$refs.test1.innerText);// 你好,世界!
});
},
從上面例子中,在created生命周期中操作了DOM,但是我們都知道created生命周期只是初始化了數(shù)據(jù),這期間是還沒有渲染DOM的,如果我們直接操作DOM是找不到DOM元素的,那么問(wèn)題來(lái)了:為什么放在nextTick中就可以獲取到了DOM元素呢?這不是很明顯嗎,等到DOM渲染完才調(diào)用不就獲取到了嗎,從而知道了nextTick作用就是用來(lái)等下次DOM渲染完才去調(diào)用nextTick內(nèi)的DOM操作代碼
。那么問(wèn)題又來(lái)了,nextTick究竟做了什么?下面我們一起從源碼層面來(lái)分別分析Vue2和Vue3版本的nextTick原理是啥。
由于Vue暴露給開發(fā)者的是nextTick這個(gè)方法,在這個(gè)方法中主要做了三件事,回調(diào)函數(shù)的添加、延遲執(zhí)行回調(diào)函數(shù)、判斷當(dāng)前的nextTick是否傳入回調(diào)函數(shù)。不傳的話,是一個(gè)Promise,this.$nextTick.then(()=>{}),按Promise處理。
回調(diào)函數(shù)添加入callbacks數(shù)組,因?yàn)榭赡苡卸鄠€(gè)nextTick函數(shù)在當(dāng)前作用域中。
判斷當(dāng)前nextTick是否已經(jīng)標(biāo)記為pending=true,也就是正在執(zhí)行,如果不是就執(zhí)行timerFunc(異步執(zhí)行函數(shù) 用于異步延遲調(diào)用 flushCallbacks 函數(shù))。timerFunc的執(zhí)行,判斷當(dāng)前環(huán)境是否支持promise、MutationObserver、setImmediate、setTimeout,優(yōu)先級(jí)高低從前到后,分四種情況:
優(yōu)先使用Promise,如果當(dāng)前環(huán)境支持promise,nextTick默認(rèn)優(yōu)先使用promise去執(zhí)行延遲回調(diào)函數(shù),timerFunc執(zhí)行的是Promise,promise是es6下的語(yǔ)法,如果當(dāng)前環(huán)境只支持es6以語(yǔ)法下的,只能考慮后面支持情況了。
支持MutationObserver,HTML5的api,中文意思是:修改的監(jiān)聽,MutationObserver用來(lái)監(jiān)聽DOM的變動(dòng)
,比如節(jié)點(diǎn)的增減、屬性的變動(dòng)、文本內(nèi)容的修改等都會(huì)觸發(fā)MutationObserver事件。注意地,與事件不同,事件是同步觸發(fā),DOM的變動(dòng)會(huì)立即觸發(fā)事件,而MutationObserver事件是異步觸發(fā),DOM不會(huì)立即觸發(fā),需要等當(dāng)前所有DOM操作完畢才會(huì)觸發(fā)。
MutationObserver有7個(gè)屬性:
childList
(true,監(jiān)聽子節(jié)點(diǎn)的變動(dòng))、attributes
(true,監(jiān)聽屬性的變動(dòng))、characterData
(true,監(jiān)聽節(jié)點(diǎn)內(nèi)容或節(jié)點(diǎn)文本的變動(dòng))、subtree
(是否應(yīng)用于該節(jié)點(diǎn)的所有后代節(jié)點(diǎn))、attributeOldValue
(觀察attributes變動(dòng)時(shí),是否需要記錄變動(dòng)前的屬性值)、characterDataOldValue
(觀察characterData變動(dòng)時(shí),是否需要記錄變動(dòng)前的值)、attributeFilter
(數(shù)組,表示需要觀察的特定屬性(比如[‘class’,‘src’])。
為什么需要?jiǎng)?chuàng)建一個(gè)文本節(jié)點(diǎn)?因?yàn)樵谶@里操作DOM保證瀏覽器頁(yè)面是最新DOM渲染的,雖然看來(lái)好像是沒什么作用,但這是保證拿到的DOM是最新的。
支持setImmediate、setTimeout,setImmediate即時(shí)計(jì)時(shí)器立即執(zhí)行工作,它是在事件輪詢之后執(zhí)行,為了防止輪詢阻塞,每次只會(huì)調(diào)用一個(gè)。setTimeout按照一定時(shí)間后執(zhí)行回調(diào)函數(shù)。
好了好了,到了現(xiàn)在,我們都知道nextTick做了什么吧,但是我們有沒有想過(guò)這樣的一個(gè)問(wèn)題:既然都是異步回調(diào)執(zhí)行等待DOM更新后才去調(diào)用操作DOM的代碼,那么這個(gè)機(jī)制又是什么原理?這就是JS的執(zhí)行機(jī)制有關(guān)了,涉及宏任務(wù)與微任務(wù)的知識(shí),我們先來(lái)看看這樣的一道題:
console.log('同步代碼1');
setTimeout(function () {
console.log("setTimeout");
}, 0);
new Promise((resolve) => {
console.log('同步代碼2')
resolve()
}).then(() => {
console.log('promise.then')
})
console.log('同步代碼3');
我們可能會(huì)問(wèn)上面的輸出是個(gè)啥,首先js是單線程,所以在js程序運(yùn)行中只有一個(gè)執(zhí)行棧,實(shí)現(xiàn)不了多線程,所以就需要任務(wù)均衡分配,通俗的講,按任務(wù)急優(yōu)先處理原則,js中分為同步任務(wù)和異步任務(wù),異步任務(wù)又分為宏任務(wù)和微任務(wù),同步任務(wù)先入棧,程序會(huì)先把執(zhí)行棧中的所有同步任務(wù)執(zhí)行完,再去判斷是否有異步任務(wù),而異步任務(wù)中微任務(wù)的優(yōu)先級(jí)高于宏任務(wù)。如果當(dāng)前執(zhí)行棧為空,而微任務(wù)隊(duì)列不為空,就先執(zhí)行微任務(wù),等把所有微任務(wù)執(zhí)行完,最后才會(huì)考慮宏任務(wù)。而上面代碼中Promise是屬于微任務(wù)
,而setTimeout是宏任務(wù)
,所以上面的輸出為:
// 同步代碼1
// 同步代碼2
// 同步代碼3
// promise.then
// setTimeout
傳入回調(diào)函數(shù)參數(shù)使用:
s.$nextTick(()=>{
// ...操作DOM的代碼
})
不傳入回調(diào)函數(shù)參數(shù)使用:
// 方式一
this.$nextTick().then(()=>{
// ...操作DOM的代碼
})
// 方式二
await this.$nextTick();
// 后寫操作DOM的代碼
Vue3版本就沒有Vue2版本的那么多環(huán)境支持,nextTick封裝成了一個(gè)Promise異步回調(diào)函數(shù)執(zhí)行。
// Vue3.2.45
// core-main\core-main\packages\runtime-core\src
export function nextTick<T = void>(
this: T,
fn?: (this: T) => void
): Promise<void> {
const p = currentFlushPromise || resolvedPromise
return fn ? p.then(this ? fn.bind(this) : fn) : p
}
傳入回調(diào)函數(shù)使用
import { nextTick } from 'vue' // 引入
setup () {
nextTick(()=>{
// ...操作DOM的代碼
})
不傳入回調(diào)函數(shù)的使用
import { nextTick } from 'vue' // 引入
setup () {
// 方式一
nextTick().then(()=>{
// ...操作DOM的代碼
})
// 方式二
await nextTick();
// 后寫操作DOM的代碼
}
以上就是關(guān)于“Vue的this.$nextTick怎么使用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
新聞名稱:Vue的this.$nextTick怎么使用
路徑分享:http://chinadenli.net/article0/geogio.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、外貿(mào)建站、面包屑導(dǎo)航、網(wǎng)站策劃、關(guān)鍵詞優(yōu)化、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)