使用this.$nextTick()获取不到数据更新后的this.$refs.xxx.及场景分析

 更新时间:2023年02月06日 09:46:17   作者:Rised  
今天遇到了这样一个场景,在数据更新之后,使用this.$nextTick(()=>{console.log(this.$refs.xxx)}) 获取不到改dom,但是用setTimeout能够获取到,在此记录一下,感兴趣的朋友跟随小编一起看看吧

使用this.$nextTick()获取不到数据更新后的this.$refs.xxx.

今天遇到了这样一个场景,在数据更新之后,使用this.$nextTick(()=>{console.log(this.$refs.xxx)}) 获取不到改dom,但是用setTimeout能够获取到,在此记录一下。

先看代码

  
<!--这是模板代码,父级用的v-else-if,与父级同级的还有两个盒子,分别用v-if和v-else控制着-->
<div ref="articleContent" class="right" v-html="articles.content"></div>
 
 
 
//这是script代码
 
 mounted() {
    
        this.getArticlesDetail()
    
  },
  methods: {
   async getArticlesDetail(){
        try {
            
            const {data}= await getArticlesDetail(this.articleId);
            /* vue数据更新是异步的 ,在这一步数据加载出来,但是组件还没没有渲染出来,因为在组件中有个v-if判断,在数据加载出来之后,才能渲染出来组件*/
            /* console.log(this.$refs.articleContent) */
            /* 所以要放在定时器是异步执行,试了用this.$nextTick,不行 */
          /*  */
            this.articles = data
            /* 只能用setitmeout是因为数据在在下个Event Loop中也出不来,这是因为v-if中的条件在下次事件循环中也不一定能够满足。但是setTimeout的执行时机是没有办法确定前边的任务到底需要多长时间执行完 */
              this.$nextTick(() => {
                console.log(this.$refs.articleContent)
            });
            console.log(data)
        } catch (error) {
            if(error.response && error.response.status===404){
                this.errStatus=404;
                this.$toast('服务器错误')
            }
            console.log(error)
            this.$toast('请求失败,请稍后再试')
        }
        /* 无论成功失败都要调用loading为false,关闭它 */
        this.loading=false
    }
  },

 这是控制台打印的效果.

 获取不到.

vue官网中对于vue.nextTick()中的解释:

 也就是说在下个事件循环中没有满足v-if中的条件,所以没有获取到数据。

在vue 中的devtools中 可以获取到。

然后我们修改成setTimeout

  
<!--这是模板代码,父级用的v-else-if,与父级同级的还有两个盒子,分别用v-if和v-else控制着-->
<div ref="articleContent" class="right" v-html="articles.content"></div>
 
 
 
//这是script代码
 
 mounted() {
    
        this.getArticlesDetail()
    
  },
  methods: {
   async getArticlesDetail(){
        try {
            
            const {data}= await getArticlesDetail(this.articleId);
            /* vue数据更新是异步的 ,在这一步数据加载出来,但是组件还没没有渲染出来,因为在组件中有个v-if判断,在数据加载出来之后,才能渲染出来组件*/
            /* console.log(this.$refs.articleContent) */
            /* 所以要放在定时器是异步执行,试了用this.$nextTick,不行 */
          /*  */
            this.articles = data
            /* 只能用setitmeout是因为数据在在下个Event Loop中也出不来,这是因为v-if中的条件在下次事件循环中也不一定能够满足。但是setTimeout的执行时机是没有办法确定前边的任务到底需要多长时间执行完 */
              setTimeout(() => {
                console.log(this.$refs.articleContent)
            });
            console.log(data)
        } catch (error) {
            if(error.response && error.response.status===404){
                this.errStatus=404;
                this.$toast('服务器错误')
            }
            console.log(error)
            this.$toast('请求失败,请稍后再试')
        }
        /* 无论成功失败都要调用loading为false,关闭它 */
        this.loading=false
    }
  },

这是控制台打印的效果

 可以看出来有效果.

在vue中的devtools中也有,

这是为什么呢? 

只能用setitmeout是因为数据在在下个Event Loop中也出不来,这是因为v-if中的条件在下次事件循环中也不一定能够满足。但是setTimeout的执行时机是没有办法确定前边的任务到底需要多长时间执行完,所以使用setTimeout会更好。

补充:详解Vue中this.$nextTick()用法

语法:

this.$nextTick( [ callback ] )

用法: 

 this.$nextTick将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上,等同于updated生命周期函数

updated用法:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。

示例: 

下面讲解一个点击按钮是输入框聚焦的示例:

<template>
  <div>
      <input ref="myInp" type="text" placeholder="这是一个输入框" v-if="isShow">
      <button v-else @click="btn">点击我进行搜索</button>
  </div>
</template>
 
<script>
 
// 获取到输入框
// 输入框调用事件方法focus()达到聚焦行为
export default {
    data(){
        return {
            isShow: false
        }
    },
    methods: {
        btn(){
            this.isShow = true;
 
            this.$refs.myInp.focus(); // 没有效果
            
            // 原因: data变化更新DOM是异步的
            // 输入框还没有挂载到真实DOM上
            // 解决:
            // this.$nextTick(() => {
            //     this.$refs.myInp.focus()
            // })
        }
        //async btn(){  
        //    this.isShow = true;
        //    
        //    // 扩展: await取代回调函数
        //    // $nextTick()原地返回Promise对象
        //    await this.$nextTick()
        //    this.$refs.myInp.focus()
        //}
    },
     //扩展
    updated(){  
     // this.$refs.myInp.focus()
    
    }
}
</script>

 直接在methods获取DOM调用聚焦方法是没有效果的,更改之后的文本是需要 dom 更新之后才会实现的,就像我们把将要打印输出的代码放在 setTimeout(fn, 0) 中,这时候用this.$nextTick就能合理解决此问题,如果我们想进页面就处于聚焦状态的话就可以使用updated生命周期函数,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作

到此这篇关于使用this.$nextTick()获取不到数据更新后的this.$refs.xxx.及场景分析的文章就介绍到这了,更多相关this.$nextTick()获取不到数据内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于vue.js组件数据流的问题

    关于vue.js组件数据流的问题

    本篇文章主要介绍了关于vue.js组件数据流的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Vue.js事件处理器与表单控件绑定详解

    Vue.js事件处理器与表单控件绑定详解

    这篇文章主要为大家详细介绍了Vue.js事件处理器与表单控件绑定详解的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • vue router返回到指定的路由的场景分析

    vue router返回到指定的路由的场景分析

    这篇文章主要介绍了vue router返回到指定的路由的场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • php+vue3实现点选验证码功能

    php+vue3实现点选验证码功能

    这篇文章主要介绍了php+vue3实现点选验证码,本文通过实例代码给大家介绍的详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2023-11-11
  • vue.js路由跳转详解

    vue.js路由跳转详解

    这篇文章主要为大家详细介绍了vue.js路由跳转的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • vue父组件传值子组件报错Avoid mutating a prop directly解决

    vue父组件传值子组件报错Avoid mutating a prop directly解决

    这篇文章主要为大家介绍了vue父组件传值子组件报错Avoid mutating a prop directly解决,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • vue通过url方式展示PDF的几种方法

    vue通过url方式展示PDF的几种方法

    小编最近接手的项目中有个需求,前端显示后端返回的PDF格式的文件,下面这篇文章主要给大家介绍了关于vue通过url方式展示PDF的几种方法,需要的朋友可以参考下
    2023-01-01
  • 详解vue axios二次封装

    详解vue axios二次封装

    这篇文章给大家分享了vue axios二次封装的相关知识点等内容以及实例代码,有兴趣的朋友可以参考学习下。
    2018-07-07
  • vue实现自定义组件挂载原型上

    vue实现自定义组件挂载原型上

    这篇文章主要介绍了vue实现自定义组件挂载原型上方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • VUE项目中引入vue-router的详细过程

    VUE项目中引入vue-router的详细过程

    vue-router 也叫 vue 路由,根据不同的路径,来执行不同的组件,这篇文章主要介绍了VUE项目中引入vue-router,需要的朋友可以参考下
    2023-05-05

最新评论