首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Vue.js 悄悄更新 DOM?99% 的开发者都没注意到这个细节!

在前端开发中,我们经常需要操作 DOM 元素。而在 Vue.js 中,由于其响应式系统的特性,DOM 更新是异步的。这意味着,当你修改数据后,并不能立即获取到更新后的 DOM 状态。这时候,nextTick就闪亮登场了!它如同一位幕后功臣,默默地确保你的代码在 DOM 更新完成后才执行,避免了各种潜在的 bug 和麻烦。

为什么要用 nextTick?

当你正在构建一个动态列表,当用户点击按钮添加新项时,你需要获取列表的最新高度来进行一些计算。如果你直接在数据更新后获取高度,很可能得到的是旧的高度,因为 DOM 还没有来得及更新。

<div>

<ul ref="myList">

<li v-for="item in items">{{ item }}</li>

</ul>

<button @click="addItem">添加项</button>

</div>

export default {

data() {

return {

items: [1, 2, 3]

};

},

methods: {

addItem() {

this.items.push(this.items.length + 1);

// 错误示范:此时 DOM 尚未更新

// console.log(this.$refs.myList.offsetHeight);

this.$nextTick(() => {

// 正确姿势:在 nextTick 回调中获取最新高度

console.log(this.$refs.myList.offsetHeight);

});

}

}

};

在这个例子中,只有在$nextTick的回调函数中,才能获取到正确的列表高度。这是因为$nextTick巧妙地利用了 JavaScript 的事件循环机制,将回调函数推迟到 DOM 更新之后执行。

nextTick 的实现原理

Vue 的nextTick并非黑魔法,其核心原理在于利用了微任务队列。它会优先使用Promise,如果浏览器不支持,则会尝试使用MutationObserver,最后才会降级到setTimeout。

function myNextTick(callback) {

return new Promise(resolve => {

if (typeof MutationObserver !== 'undefined') {

const observer = new MutationObserver(() => {

resolve(callback && callback());

});

const textNode = document.createTextNode('');

observer.observe(textNode, { characterData: true });

textNode.data = ' ';

} else if (typeof Promise !== 'undefined') {

Promise.resolve().then(() => {

resolve(callback && callback())

});

} else {

setTimeout(() => {

resolve(callback && callback())

}, 0);

}

});

}

// 测试

let counter = 0

myNextTick(()=>{console.log(++counter)})

console.log(++counter)

myNextTick(async () => { await new Promise((resolve)=>{ setTimeout(()=>{ resolve()},1000)}); console.log(++counter)})

console.log(++counter)

这段代码模拟了nextTick的核心逻辑。它优先使用MutationObserver,创建一个观察者来监听文本节点的变化,并在变化发生后执行回调。如果浏览器不支持MutationObserver,则使用Promise,将回调放入微任务队列。最后,如果Promise也不支持,则使用setTimeout模拟异步执行。注意,即便使用了MutationObserver,当回调函数是一个异步操作的时候,nextTick的promise需要等待回调函数返回的promise状态改变后,才能改变状态。这个时候nextTick就变成了一个宏任务。

nextTick 的应用场景

除了获取更新后的 DOM 状态,nextTick还有很多其他应用场景,例如:

• 在组件生命周期钩子中,需要操作 DOM 时。

• 在动画过渡效果中,需要在动画完成后执行某些操作。

• 需要根据 DOM 状态进行一些计算或逻辑处理时。

nextTick是 Vue.js 中一个非常实用且重要的工具,它帮助我们更好地管理 DOM 更新,避免了各种潜在的错误。理解其原理和应用场景,能让你写出更高效、更健壮的 Vue.js 代码。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OqIv-StccvJyL2aXqftzJNZQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券