Vue nextTick使用
原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。
用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
通俗来说就是修改data后dom不会马上改变 可以调用 this.$nextTick 来立刻获取到data改变后dom数据。
(比如我们通过ajax请求数据修改dom,发生ajax请求后立即使用 this.$refs获取dom,结果为undfined,因为修改data后dom不会马上改变,可以通过this.$nextTick)
this.$nextTick(()=>{ this.$refs.xxx=xxx })
例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>vue生命周期学习</title> <script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script> </head> <body> <div id="app"> <div ref="msgDiv">{{msg}}</div> <div v-if="msg1">Message1: {{msg1}}</div> <div v-if="msg2">Message2: {{msg2}}</div> <div v-if="msg3">Message3: {{msg3}}</div> <button @click="changeMsg"> Change the Message </button> </div> </body> <script> var vm = new Vue({ el:'#app', data:{ msg:'hello vue', msg1:'', msg2:'', msg3:'' }, methods:{ changeMsg(){ this.msg = "Hello world." this.msg1 = this.$refs.msgDiv.innerHTML this.$nextTick(() => { this.msg2 = this.$refs.msgDiv.innerHTML }) this.msg3 = this.$refs.msgDiv.innerHTML } } }) </script> </html>
打印结果:
Hello world
Message1:hello vue
Message2:Hello world 使用了nextTick 快速获取更新后的dom
Message3:hello vue
由上可看出点击按钮更新数据后,this.msg中的信息很快替换,而从dom中拿到的数据msg1,不会立即同步更新到dom上,同理从dom中拿到的数据msg3,也不会立即同步更新到dom上。 (dom数据不会立刻改变)
vue dom更新循环机制
Vue 是异步执行 DOM 更新的
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
就好比 有两根线,一根线A为执行栈,另一根线B为任务队列。当次循环是,有异步任务就在B线加个事件。当A线执行完成就执行B线的事件。B执行完,则完成本次循环。又重新开始新的循环A线 第一次【 A→B(本次结束)】→第二次【A→B(本次结束)】……
也就是说Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
使用场景
例如:需要在created 初始就要对dom进行操作。而我们知道dom是在mounted阶段挂载渲染好的。这时就要使用this.$nextTick