$nextTick和$forceUpdate

南風知我意NY發表於2019-04-04

vm.$nextTick( [callback] )

官方解釋: 將回撥延遲到下次 DOM 更新迴圈之後執行

要理解這句話,首先要了解一下vue的非同步更新佇列,Vue 非同步執行 DOM 更新。只要觀察到資料變化,不會立即更新DOM,Vue 將開啟一個佇列,並緩衝在同一事件迴圈中發生的所有資料改變。如果同一個 資料被的多次 改變,只會被推入到佇列中一次。例如,當你設定 vm.someData = 'new value' ,對應的DOM更新會被推到一個佇列裡,該元件不會立即重新渲染,會在當前tick完畢後,在下一個tick中渲染DOM。在事件迴圈中,每進行一次迴圈操作稱為tick。而nextTick函式就是vue提供的一個例項方法,資料更新後等待下一個tick裡Dom更新完後執行回撥,回撥的 this 自動繫結到呼叫它的例項上。

例如:

html: 
<span class="test">{{egData}}</span>
<el-button @click="changeData">改變</el-button>

js:
new Vue({
	data () {
		return {
			egData: 'old Message'
		}
	}
    methods: {
        changeData () {
          this.egData = 'new Message'
          console.log($('.test').html(), '-----------------------')
        }
  	}
})
複製程式碼

結果: 第一次點選輸出 old Message -----------------------,第二次點選輸出 new Message -----------------------

使用$nextTick:

js:
new Vue({
	data () {
		return {
			egData: 'old Message'
		}
	}
    methods: {
        changeData () {
          this.egData = 'new Message'
          this.$nextTick(function () {
          	console.log($('.test').html(), '-----------------------')
          })
          
        }
  	}
})
複製程式碼

結果:不管第幾次點選,都輸出 new Message -----------------------

$nextTick使用場景:

1、資料更新後想要馬上操作新的DOM,需要把操作寫在nextTick的回撥裡

2、在created鉤子函式裡需要操作DOM,也可以把操作寫在nextTick的回撥裡,(created鉤子函式裡還沒有掛載dom,所以直接操作會有問題)

$forceUpdate()

迫使Vue例項重新(rander)渲染虛擬DOM,注意並不是重新載入元件。結合vue的生命週期,呼叫$forceUpdate後只會觸發beforeUpdate和updated這兩個鉤子函式,不會觸發其他的鉤子函式。它僅僅影響例項本身和插入插槽內容的子元件,而不是所有子元件。

$forceUpdate()使用場景:

1、當在data裡沒有顯示的宣告一個物件的屬性,而是之後給該物件新增屬性,這種情況vue是檢測不到資料變化的,可以使用$forceUpdate()

html:

<span class="test">{{egData.value}}</span>
<el-button @click="changeData">改變</el-button>

js:
egData: {}

...


changeData () {
    this.egData.value = 'oldValue'
    this.$forceUpdate()  // dom會更新
}

複製程式碼

但是這種做法並不推薦,官方說如果你現在的場景需要用forceUpdate方法 ,那麼99%是你的操作有問題,如上data裡不顯示宣告物件的屬性,之後新增屬性時正確的做法時用 vm.$set() 方法,所以forceUpdate請慎用

相關文章