天天看點

【vue】聽說$nexttick,$set,$forceupdate都能起到更新視圖的作用,那你知道他們的差別嗎?

前言

想必很多小夥伴在使用vue時,都遇到過明明修改data裡的資料了,但是視圖卻不更新的情況吧,這時候有經驗的小夥伴,二話不說直接調用this.$forceupdate()強制更新頁面,管他啥情況,刷就完事了,我屬于是整個一個大無語。

$nexttick

将回調延遲到下次 DOM 更新循環之後執行。在修改資料之後立即使用它,然後等待 DOM 更新。它跟全局方法 

Vue.nextTick

 一樣,不同的是回調的 

this

 自動綁定到調用它的執行個體上。

        上面摘抄自vue官網,很多小夥伴可能看不懂,首先你要先知道vue的異步更新隊列。

        可能你還沒有注意到,Vue是異步執行DOM更新的,一旦觀察到資料變化,Vue就會開啟一個隊列,然後把在同一個事件循環(event loop)中觀察到的資料變化的watcher推送進這個隊列。如果這個watcher被觸發多次,隻會被推送到隊列一次。這種緩沖行為可以有效去掉重複資料造成不必要的計算和DOM操作。而在下一個事件循環時,Vue會清空隊列,并進行必要的DOM更新。

        “說的啥玩意兒,一句沒看懂”

         “蒸滴撈,這都看不懂,給你打個比方,如果你要修改一個資料,還連續修改了很多次,程式總不能不斷更新n次視圖叭,這也太消耗性能了,是以實際上vue隻會在你改了半天資料後,對你最終的結果進行更新。懂了嗎?”

         “哇,這麼牛嗎,那nextick是怎麼回事呢?”

         “聽好了,哥一句話讓你頓悟,它其實就是用來知道什麼時候DOM更新完成的。”

         “666,不明覺厲,但是知道了有什麼用呢?”

         “比如你在修改資料之後,想要操作dom,你經常會發現擷取到dom綁定的值還是舊值”

         小明突然大聲喊道:“啊對對對,就是這樣,煩死我了,怎麼解決它呢”

         “别急,你要先知道為什麼,其實就是剛剛說的,你改了資料,它還擱那兒排序等着看你最後的結果呢,這時候dom還沒更新。是以如果你想拿到新值,nexttick就派上用場了。因為它能知道dom的更新時間,你就可以在它的回調函數裡去進行操作,就能拿到新值了”

         “哇,學到了,感謝大佬,還有個問題,怎麼我總聽說别人用$nexttick更新視圖,我聽你這意思它并沒有起到更新視圖的作用啊”

         “小夥子有長進,還能看出點東西。是的,網上總有些人亂扯,說用$nexttick更新視圖,其實它隻是讓你的操作在視圖更新後才執行而已”

         “好的,謝謝大佬,我這就拿個小本本記下來”

$set

向響應式對象中添加一個 property,并確定這個新 property 同樣是響應式的,且觸發視圖更新。它必須用于向響應式對象上添加新 property,因為 Vue 無法探測普通的新增 property (比如 

this.myObject.newProperty = 'hi'

)

資料更新但視圖沒更新,這種情況往往是我們定義了個對象,給這個對象添加了新的屬性。

我們要知道,vue2的雙向綁定原理它是通過Object.defineProperty()實作的,在初始化時,vue會把data中的資料加工成響應式的。然而如果你往這個資料上添加了新屬性,顯然,它沒有被加工成響應式資料,那麼視圖怎麼會更新呢?

       “那我該怎麼做才能重新整理視圖呢?”

       “你分析一下就能想到,無非就是兩種方案,一種是把新加的屬性添加響應式,一種就是管他響應不響應的,用硬辦法強制重新整理下頁面”

       “願聞其翔”

       “第一種就是這裡要說的$set,這是vue提供的api,你用它給對象添加屬性就可以了”

       “好的,我去看看怎麼用”

       “不用麻煩了,很簡單的,看下面”

錯誤寫法:this.$set(key,value)(ps: 可能是vue1.0的寫法)

mounted () {
    this.$set(this.student.age, 24)
}      

正确寫法:this.$set(this.data,”key”,value’)

$forceupdate

迫使 Vue 執行個體重新渲染。注意它僅僅影響執行個體本身和插入插槽内容的子元件,而不是所有子元件。

$forceUpdate的原理很簡單,即使強制觸發update聲明周期,重新渲染下dom:

Vue.prototype.$forceUpdate = function () {
    const vm: Component = this
    if (vm._watcher) {
        vm._watcher.update()
    }
}
           

總結

1. $nexttick并不是真正意義上的更新視圖,而是等視圖更新後再執行某些操作

2. 雖然$forceUpdate和$set都能起到更新視圖的效果,但是前者并不推薦使用,一是,官方都說了,如果你都到了要用$forceupdate的地步了,那你十有八九是操作有問題;二是能用$set解決的問題,為什麼要用$forceupdate這種更消耗性能的方法呢,如果用了,估計是你偷懶!

本期部落格參與了【新星計劃】,還請大家三連支援一下🌟🌟🌟感謝感謝💓💓💓