Vue this.$nextTick原理

  雖然 Vue.js 一般鼓勵開發人員沿着「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們確實要這麼作。好比一個新聞滾動的列表項。若是在這裏須要操做dom, 應該是等待 Vue 完成更新 DOM以後。javascript

1、新聞滾動列表html

一、在created函數中獲取後臺數據;java

二、模板引擎中用v-for生成列表項;dom

三、調用滾動函數,假設該滾動函數式原生方法寫的;異步

四、何時開始調用滾動函數比較合適呢?函數

 

2、this.$nextTick()性能

官方解釋:將回調延遲到下次 DOM 更新循環以後執行。在修改數據以後當即使用它,而後等待 DOM 更新。它跟全局方法 Vue.nextTick 同樣,不一樣的是回調的 this 自動綁定到調用它的實例上。this

Vue.component('example', {
  template: '<span>{{ message }}</span>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  methods: {
    updateMessage: function () {
      this.message = 'updated'
      console.log(this.$el.textContent) // => 'not updated'
      this.$nextTick(function () {
        console.log(this.$el.textContent) // => 'updated'
      })
    }
  }
})

 

3、新聞滾動列表中的this.$nextTick()放哪裏?spa

  由於數據是根據請求以後獲取的,因此應該放到請求的回調函數裏面。component

 

4、原理【重點】

前面只是利用一個例子引入話題。

在進行獲取數據後,須要對新視圖進行下一步操做或者其餘操做時,爲何獲取不到 DOM呢?

緣由:

這裏就涉及到 Vue 一個很重要的概念:異步更新隊列(JS運行機制 、 事件循環)。

Vue 在觀察到數據變化時並非直接更新 DOM,而是開啓一個隊列,並緩衝同一事件循環中發生的全部數據改變。

在緩衝時會去除重複數據,從而避免沒必要要的計算和DOM操做。

而後,在下一個事件循環 tick 中,Vue 刷新隊列並執行實際(已去重的)工做。

因此若是用 for 循環來動態改變數據100次,其實它只會應用最後一次改變,若是沒有這種機制,DOM就要重繪100次,是一個很大的開銷,損耗性能。

例子:

//改變數據
vm.message = 'changed'

//想要當即使用更新後的DOM。這樣不行,由於設置message後DOM尚未更新
console.log(vm.$el.textContent) // 並不會獲得'changed'

//這樣能夠,nextTick裏面的代碼會在DOM更新後執行
Vue.nextTick(function(){
    console.log(vm.$el.textContent) //能夠獲得'changed'
})

  

5、常見應用

點擊按鈕顯示本來以 v-show = false 隱藏起來的輸入框,並獲取焦點。

showsou(){
  this.showit = true //修改 v-show
  document.getElementById("keywords").focus()  //在第一個 tick 裏,獲取不到輸入框,天然也獲取不到焦點
}

//修改
showsou(){
  this.showit = true
  this.$nextTick(function () {
    // DOM 更新了
    document.getElementById("keywords").focus()
  })
}
相關文章
相關標籤/搜索