Vue nextTick获取更新后的DOM的实现

 更新时间:2022年01月25日 09:14:36   作者:Skuld_yi's Blog  
本文主要介绍了Vue nextTick获取更新后的DOM的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前两天在开发时遇到一个需求:打开对话框的时候自动聚焦其中的输入框。由于原生的 autofocus 属性不起作用,需要使用组件库提供的 focus 方法手动手动获取焦点。于是有如下代码:

<el-button @click="openDialog">点击打开 Dialog</el-button>

<el-dialog :visible.sync="dialogVisible">
  <el-input v-model="input" ref="input"></el-input>
</el-dialog>
methods: {
  openDialog() {
    this.dialogVisible = true;
    const input = this.$refs.input;
    input.focus();
  },
},

结果报错了,原因是没有获取到 input 组件;通过 log,也验证了 this.$refs.input 的值确实是 undefined。但是经过测试,如果对话框默认状态是打开的,就不会报错;明明组件就在那,为什么获取不到呢?

生命周期 update

经过分析,这种现象是由于 Vue 实例的更新机制造成的。从下方的生命周期图(局部)中可以看出,组件装载好之后,遇到数据变化时将重新渲染虚拟 DOM(可以理解为 HTML 中的组件节点)。在本例中,隐藏的 Dialog 组件(以及其中的 input 组件)本来并没有渲染在 DOM 中,是在观察到 dialogVisible 属性变为 true 后再进行更新渲染的。

而网页渲染通常是一个异步任务,因此在 visible 属性刚刚更改时(一个函数中是同步过程),DOM 渲染还没有进行,因此自然获取不到此时还不存在的 input 组件了。

关于异步、JS任务队列、宏任务与微任务等概念的更多介绍,可参考博文JS多线程:任务队列

为了更直观地展示这个过程,可以在更新前后的钩子函数中试图获取组件并进行打印:

beforeUpdate() {
  console.log("beforeUpdate");
  const input = this.$refs.input;
  console.log(input);
},
updated() {
  console.log("updated");
  const input = this.$refs.input;
  console.log(input);
},
methods: {
  openDialog() {
    this.dialogVisible = true;
    console.log("click open");
  },
},

结果如下,可以验证之前的分析和猜想:

click open
beforeUpdate
undefined
updated
VueComponent {...}

Vue.nextTick

为了解决这个问题,Vue 提供了全局 api Vue.nextTick(),它的作用是提供下次 DOM 更新之后的回调。也就是说,在更新数据后调用 api,就能够获取到重新渲染后的 DOM 并进行相关操作。

nextTick 方法可以广泛适用于各种需要在数据更新后对相关 DOM 进行操作的情景,例如 v-if 、watch 等。

在上文的例子中再加入 nextTick:

openDialog() {
  this.dialogVisible = true;
  console.log("click open");
  this.$nextTick(function () {
    console.log("next tick");
    const input = this.$refs.input;
    console.log(input);
    input.focus();
  });
},

可以看到,回调确实是在 DOM 更新之后,也就是 updated 执行之后才执行的。获取组件与手动获得焦点的操作也能够正确执行了。

click open
beforeUpdate
undefined
updated
VueComponent {...}
next tick
VueComponent {...}

Promise

如果没有提供回调参数,并且浏览器支持 Promise,调用 nextTick 将返回一个 Promise。也就是说下面几种写法是等价的(环境支持的情况下):

Vue.nextTick(function () {...})
Vue.nextTick(() => {...})

Vue.nextTick().then(function () {...})
Vue.nextTick().then(() => {...})

关于 Promise 的介绍和用法,可以参考博文 JS Promise

结语&参考资料

以上是个人对 Vue 中 nextTick api 的一些理解与思考,希望能给你提供帮助。如果有问题或疏漏之处,欢迎在评论中讨论与指正。

参考资料:

Vue 文档 - api

Vue 文档 - 实例

到此这篇关于Vue nextTick获取更新后的DOM的实现的文章就介绍到这了,更多相关Vue nextTick获取更新后的DOM内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue极简生成器 Vuepress的实现

    Vue极简生成器 Vuepress的实现

    本文主要介绍了Vue极简生成器 Vuepress的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧<BR>
    2022-06-06
  • Vue项目WebPack打包删除注释和console

    Vue项目WebPack打包删除注释和console

    这篇文章主要介绍了Vue项目WebPack打包删除注释和console,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • Vue子父组件之间传值的三种方法示例

    Vue子父组件之间传值的三种方法示例

    Vue的组件化给前端开发带来极大的便利,下面这篇文章主要给大家介绍了关于Vue子父组件之间传值的三种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • vue $router和$route的区别详解

    vue $router和$route的区别详解

    这篇文章主要介绍了vue $router和$route的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • UniApp中实现类似锚点定位滚动效果

    UniApp中实现类似锚点定位滚动效果

    一个uniapp小程序的项目,我们需要实现一个非常实用的功能——类似于锚点定位的交互效果,即在首页中有多个tab(分类标签),每个tab对应着不同的模块,当用户点击某个分类的tab时,需要流畅地滚动到对应的内容位置,提供更好的用户体验,
    2023-10-10
  • vue 单元测试的推荐插件和使用示例

    vue 单元测试的推荐插件和使用示例

    单元测试是软件开发非常基础的一部分。单元测试会封闭执行最小化单元的代码,使得添加新功能和追踪问题更容易。Vue 的单文件组件使得为组件撰写隔离的单元测试这件事更加直接。它会让你更有信心地开发新特性而不破坏现有的实现,并帮助其他开发者理解你的组件的作用。
    2021-06-06
  • 浅谈vuex 闲置状态重置方案

    浅谈vuex 闲置状态重置方案

    本篇文章主要介绍了vuex 闲置状态重置方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • vue中全局路由守卫中替代this操作(this.$store/this.$vux)

    vue中全局路由守卫中替代this操作(this.$store/this.$vux)

    这篇文章主要介绍了vue中全局路由守卫中替代this操作(this.$store/this.$vux),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Vue3.x如何设置浏览器动态Title方法

    Vue3.x如何设置浏览器动态Title方法

    这篇文章主要介绍了Vue3.x如何设置浏览器动态Title方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • vue项目结构目录超详细介绍

    vue项目结构目录超详细介绍

    这篇文章主要给大家介绍了关于vue项目结构目录超详细介绍的相关资料,Vue项目目录结构是指在开发Vue项目时,为了更好地组织和管理代码,将不同的文件按照一定的规则和层次结构进行分类和存放的方式,需要的朋友可以参考下
    2023-12-12

最新评论