赞
踩
由于vue的异步更新机制,我们在同步代码中是无法获取到更新后的dom的信息的
针对这个问题,我们有三种解决方案获取更新后的dom:
1.nextTick()
2.setTimeout()
3.在微任务中获取
因为更新是在同步任务结束后,执行微任务之前,所以上面三种方式可以得到更新后的dom。
先看代码,下面的代码中,通过点击使得绑定的按钮元素高度增加,在js中通过打印来去观察不同获取该元素信息的方式的区别。
- <template>
- <div class="page">
- <button
- @click="clickButton"
- ref="buttonRef"
- :style="{ height: `${height}px`, width: '60px' }"
- ></button>
- <div class="info">{{ height }}</div>
- </div>
- </template>
- <script setup lang="ts">
- import { nextTick, ref } from "vue";
- const height = ref(40);
- const buttonRef = ref();
- const clickButton = async () => {
- height.value = height.value + 10;
- console.log(buttonRef.value.style.height, "直接打印"); // 40px
- setTimeout(() => {
- console.log(buttonRef.value.style.height, "setTimeout0打印1"); // 50px
- }, 0);
- await console.log("dom已更新");
- setTimeout(() => {
- console.log(buttonRef.value.style.height, "setTimeout0打印2"); // 50px
- }, 0);
- setTimeout(() => {
- console.log(buttonRef.value.style.height, "setTimeout100打印"); // 50px
- }, 100);
- nextTick(() => {
- console.log(buttonRef.value.style.height, "nextTick打印"); // 50px
- });
- console.log("测试数据");
- console.log(buttonRef.value.style.height, "微任务打印"); // 50px
- };
- </script>
- <style>
- .page {
- width: 100%;
- height: 100vh;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- }
- </style>

我们可以观察到,除了在同步代码中获取按钮元素的信息,都得到了更新后的按钮高度。同时我们可以发现,nextTick中的任务是在微任务队列的末尾的,如果把这段代码提前到同步任务中也是同样的效果。
由此,我们可以得出结论,获取更新后dom的速度,微任务中获取>nextTick中获取>宏任务中获取
1.避免无限循环。如果 nextTick 的回调被添加到队列的开头,那么在执行回调的过程中再次调用 nextTick 可能会导致无限循环,因为新产生的 nextTick 任务会立即执行,从而可能不断地往队列中添加新的任务。
2.性能优化。vue的异步更新是为了让同一个Tick中的数据变化完了再更新,将任务放入末尾也是同样的目的,可以尽可能减少不必要的dom操作。
3.便于调试。如果这个任务会到处都是那么数据的变化是难以预测的。
1.nextTick的作用就是告诉vue这个dom更新好了,简单,稳定,可靠,语义强。
2.方便调试,避免无限循环,性能优化。
3.不用像settimeout一样把任务拖到下一个宏任务。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。