可能你尚未注意到,Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher 被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做上很是重要。而後,在下一個的事件循環「tick」中,Vue 刷新隊列並執行實際 (已去重的) 工做。Vue 在內部嘗試對異步隊列使用原生的 Promise.then 和 MessageChannel,若是執行環境不支持,會採用 setTimeout(fn, 0) 代替。
例如,當你設置 vm.someData = 'new value' ,該組件不會當即從新渲染。當刷新隊列時,組件會在事件循環隊列清空時的下一個「tick」更新。多數狀況咱們不須要關心這個過程,可是若是你想在 DOM 狀態更新後作點什麼,這就可能會有些棘手。雖然 Vue.js 一般鼓勵開發人員沿着「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們確實要這麼作。爲了在數據變化以後等待 Vue 完成更新 DOM ,能夠在數據變化以後當即使用 Vue.nextTick(callback) 。這樣回調函數在 DOM 更新完成後就會調用。例如:vue
<div id="example">{{message}}</div> var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // 更改數據 vm.$el.textContent === 'new message' // false Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })
在組件內使用 vm.$nextTick() 實例方法特別方便,由於它不須要全局 Vue ,而且回調函數中的 this 將自動綁定到當前的 Vue 實例上:node
Vue.component('example', { template: '<span>{{ message }}</span>', data: function () { return { message: '沒有更新' } }, methods: { updateMessage: function () { this.message = '更新完成' console.log(this.$el.textContent) // => '沒有更新' this.$nextTick(function () { console.log(this.$el.textContent) // => '更新完成' }) } } })
鉤子函數dom
一個指令定義對象能夠提供以下幾個鉤子函數 (均爲可選):異步
bind:只調用一次,指令第一次綁定到元素時調用。在這裏能夠進行一次性的初始化設置。函數
inserted:被綁定元素插入父節點時調用 (僅保證父節點存在,但不必定已被插入文檔中)。佈局
update:所在組件的 VNode 更新時調用,可是可能發生在其子 VNode 更新以前。指令的值可能發生了改變,也可能沒有。可是你能夠經過比較更新先後的值來忽略沒必要要的模板更新 (詳細的鉤子函數參數見下)。this
componentUpdated:指令所在組件的 VNode 及其子 VNode 所有更新後調用。spa
unbind:只調用一次,指令與元素解綁時調用。code
鉤子函數的參數 (即 el、binding、vnode 和 oldVnode)。component
須要注意的是:update時dom可能尚未插入文檔,componentUpdated是DOM已經插入文檔。而且所謂的「更新」這個鉤子函數的觸發條件很是寬泛,不容易把控。好比,其餘與該節點無關的相鄰節點更新,引起其佈局的重流,也會致使該鉤子函數觸發
所以,若是想要在數據更新後,操做DOM,使用指令的update, componentUpdated 須要謹慎,能夠考慮使用nextTick