深入了解 Vue.js 中的 nextTick:实现原理

今天我们来聊一聊vue中的nextTick,这是vue.js中的一个异步API,nextTick 的作用是将回调函数延迟到下次 DOM 更新周期之后执行。我们知道,在vue.js中数据是响应式的,当数据发生变化时,对应的DOM也会随着更新,但是DOM的更新并不是同步的,而是异步执行的,因此,在一些情况下,我们需要在DOM更新之后执行一些代码的话,就需要借助nextTick这个方法。

nextTick的功能与效果

话不多说,我们直接上示例,我们来看下面的这一段代码:为了不过于冗长,css省略

vue 复制代码
<template>
  <div>
    <button @click="addList">更新列表</button>
    <ul>
      <li v-for="item in list">{{ item }}</li>
    </ul>
  </div>
</template>

<script setup>
import { nextTick, ref } from 'vue'
const list = ref([])
list.value = [1,2,3,4,5,6,7,8,9,10]
const addList = () => {
  // 一次添加10个元素
  list.value.push(11,12,13,14,15,16,17,18,19,20)
  // 获取指定的元素,要求页面滚动到这个位置
  let lastDom = document.querySelector('li:last-child')
  lastDom.scrollIntoView()
}
</script>

运行之后我们会发现,虽然页面确实是滚动了,但是没有到达我们预期的位置,而是滚动到11就不动了,这是为什么呢?因为DOM的更新是异步的,而获取指定元素和滚动的执行代码是同步的,我们这里想要获取最后一个li,但实际上,DOM还没有更新完成,获取指定元素的代码就开始执行了,所以获取的并不是最后一个元素,自然也就没有达到我们想要的效果。

想要达到我们需要的效果,我们只需要把获取指定元素的代码和滚动的代码放进nextTick的回调中就好了

vue 复制代码
<script setup>
import { nextTick, ref } from 'vue'
const list = ref([])
list.value = [1,2,3,4,5,6,7,8,9,10]
const addList = () => {
  // 一次添加10个元素
  list.value.push(11,12,13,14,15,16,17,18,19,20)
  nextTick(() => {
    // 获取指定的元素,要求页面滚动到这个位置
    let lastDom = document.querySelector('li:last-child')
    lastDom.scrollIntoView()
  })
}
</script>

这样就可以达到我们想要的效果

手写一个简单的nextTick

那么怎么实现nextTick的效果呢,其实我们也可以手写一个简单的nextTick,帮助我们理解nextTick

nextTick接受一个回调函数作为形参,当页面上的DOM更新完成之后,执行回调中的代码

js 复制代码
// 创建一个简单的nextTick
function simpleNextTick(fn) { // 接受一个回调函数作为形参
    let dom = document.documentElement; // 获取文档对象
    let observer = new MutationObserver(() => { // 创建一个观察器 MutationObserver是一个内置的 JavaScript API,可以在 DOM 树中的节点发生变化时触发回调函数
        fn(); // 观察到变化后执行回调函数
    });
    observer.observe(dom, {
        attributes: true,
        childList: true,
        subtree: true
    }); // observe 是MutationObserver 的实例方法,用于观察文档对象的属性、子节点、后代节点变化
}

这样就完成了一个简单的nextTick,只需要将其引入我们的项目中就可以达到效果

相关推荐
我是一颗柠檬6 小时前
【MySQL全面教学】MySQL面试高频考点汇总Day15(2026年)
数据库·后端·mysql·面试
kyriewen7 小时前
微软用Go重写TypeScript编译器,速度提升10倍,网友:这是“背叛”还是“救赎”?
前端·typescript·ecmascript 6
Ceelog7 小时前
久坐党自救指南:屏幕前 8 小时,身体到底在经历什么
前端·后端
西陵7 小时前
Agent 为什么会陷入 Doom Loop?OpenClaw 的破解之道
前端·人工智能·ai编程
Hyyy8 小时前
普通前端续命周报——第2周
前端
swipe8 小时前
DeepAgents 实战:用多 Agent 架构搭一个深度调研助手
javascript·面试·llm
wuxinyan1238 小时前
工业级大模型学习之路030:Streamlit 企业级智能体前端工作台
前端·学习·streamlit·智能体
修己xj8 小时前
告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
前端
雪宫街道8 小时前
synchronized 锁的范围:对象锁、类锁与代码块锁
java·jvm·后端·面试
anOnion9 小时前
构建无障碍组件之Slider Pattern
前端·html·交互设计