详解vue指令与$nextTick 操作DOM的不同之处
异步更新队列
可能你还没有注意到,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 更新完成后就会调用。例如:
<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 实例上:
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) // => '更新完成' }) } } })
vue指令
钩子函数
一个指令定义对象可以提供如下几个钩子函数 (均为可选):
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 vnode 更新时调用,但是可能发生在其子 vnode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentupdated:指令所在组件的 vnode 及其子 vnode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
钩子函数的参数 (即 el、binding、vnode 和 oldvnode)。
需要注意的是:update时dom可能还没有插入文档,componentupdated是dom已经插入文档。并且所谓的“更新”这个钩子函数的触发条件非常宽泛,不容易把控。比如,其他与该节点无关的相邻节点更新,引发其布局的重流,也会导致该钩子函数触发
因此,如果想要在数据更新后,操作dom,使用指令的update, componentupdated 需要谨慎,可以考虑使用nexttick
总结
以上所述是小编给大家介绍的vue指令与$nexttick 操作dom的不同之处,希望对大家有所帮助