可能你尚未注意到,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