雖然 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() }) }