问题一
为什么在 created 中使用了 $nextTick 可以通过 Vue 的方式获取 DOM???
首先说一下为什么我会有这个疑问
- 在事件循环(Event loop)中,微任务的优先级是要大于 DOM 渲染的
- 而在 Vue 底层对于 $nextTick 的实现,如果浏览器支持 Promise,那么就是用的 Promise
- Promise.then 也是微任务
- 我这里测试是使用的谷歌浏览器,所以 $nextTick === 微任务
<div id="app" ref="app">
<span>{{count}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
count: 1
},
created() {
// 这里可以很明显的看到是有的
this.$nextTick(() => {
console.dir(this.$refs.app); // div#app
})
},
})
</script>
- 对于 nextTick,Vue 官网是这样解释的:
- 将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
- 看到这里我恍然大悟,其实在 created 生命周期中,DOM 早就渲染好了,只是在后面的生命周期中对 DOM 进行了更新
<div id="app" ref="app">
<span>{{count}}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
count: 1
},
created() {
// 这里 DOM 其实早就渲染好了,只是 Vue 在之后的生命周期中又对页面的 DOM 进行了更改
// 也就是经过 Vue 渲染的 DOM 才能使用 this.$refs 的方法去获取
// 因为 Vue 是数据驱动页面,而我们通过原生的方法在 created 中进行获取,
// 很有可能在后面的生命周期又对 DOM 进行了更改,所以最好不要这样去做
console.dir(document.querySelector("#app")); // div#app
console.dir(this.$refs.app); // undefined
},
})
</script>
问题二
- 刚才上面说到了,使用 $nextTick 获取的 DOM,是货真价实经过 Vue 更新 DOM
- 起初我也是这样想的