«

vue获取v-for异步数据dom问题怎么解决

时间:2024-8-5 09:34     作者:韩俊     分类: Javascript


这篇文章主要讲解了“vue获取v-for异步数据dom问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue获取v-for异步数据dom问题怎么解决”吧!

    vue获取v-for异步数据dom

    问题描述

    每次加载界面时,在

    mounted
    阶段,只能获取普通dom(指静态渲染的dom),获取不到v-for的dom,尽管使用
    $nextTick
    也获取不到,虽然使用
    setTimeOut
    能解决,但这种方法真的很low,作为程序员要追求完美,下面我们看看怎么完美解决这个问题。

    原因

    在v-for里的数据是异步获取的,里面的id或者class也都是动态绑定的,而mounted阶段只是实例挂载完成,这时候异步请求的数据大概率还没请求完成,从而v-for要渲染的dom肯定也还没开始渲染,这时候连异步请求的数据都获取不到,更别说需要异步数据来渲染的dom了。

    $nextTick
    是指整个视图渲染完成,注意这里不包含异步请求的数据,在整个视图渲染完成时异步数据未必能请求到。所以调用
    $nextTick
    其实也没什么两样。

    解决思路及方案

    第一种并不是很完美的方案:使用updated钩子

    updated 阶段是完成了数据更新到 DOM 的阶段(对加载回来的数据进行处理),此时,在使用document等获取dom是可以得到的。

    updated 与 mounted 不同的是,在每一次的 DOM 结构更新,Vue.js 都会调用一次 updated 钩子函数!而 mounted 钩子函数仅仅只执行一次而已。

    但是,本人不推荐这么做,因为如果项目中数据更新很频繁,虚拟dom也会跟着经常更新,如果在updated中获取dom,会造成操作过于频繁的问题,也就会多多少少影响程序性能。在vue官方也有提到。

    完美解决的方案:在异步数据获取完成时调用$nextTick获取dom

    想获取异步请求数据渲染的dom就一定得等到数据接收到后再进行相应的操作。而有同学就问了,为什么在获取到数据后还要调

    $nextTick
    呢?

    因为获取到数据之后v-for去动态渲染dom肯定也是需要一定时间的,不可能马上就能渲染完成,所以在获取到异步数据之后再等整个视图渲染完成时去获取dom是最好的选择。

    那要在

    created
    或者
    mounted
    或者在
    watch
    中获取就看个人选择了。

    created
    或者
    mounted
    中需要在获取完数据后在
    then
    或者
    await
    接受返回的数据再调用
    $nextTick
    获取dom,在watch中就直接监视请求的数据,数据改变就说明获取到了,就可以调用
    $nextTick
    获取dom了。

    vue获取DOM问题

    利用 ref 和 $refs 可以用于获取 dom 元素

    <h2 id="h" ref="myH">我是一个孤独可怜又能吃的h2</h2>
     
    mounted() {
        console.log(document.getElementById("h"));
        console.log(this.$refs.myH);
      },

    使用ref调用组件内的方法。

    <Demo ref="de"></Demo>
     
    import Demo from "./child/demo";
     
    //组件起别名ref
    let demoObj = this.$refs.de;
    //可以以此调用组件内的方法,变量等
        demoObj.fn();

    $nextTick使用

    如果我们修改某个出现在DOM里的变量,之后又要获取DOM里的变量值,那么会发现DOM里变量值并未修改成功,因为Vue更新DOM是异步的,用$nextTick解决。

    因为vue 通过异步队列控制 DOM 更新和 nextTick 回调函数先后执行。

    <p ref="myP">{{ count }}</p>
    <button @click="btn">点击count+1, 马上提取p标签内容</button>
     
    btn() {
          this.count++; // vue监测数据更新, 开启一个DOM更新队列(异步任务)
          console.log(this.count) //1
          //因为Vue更新DOM是异步的,所以count虽然完成加一,但这里的DOM还未更新。
          console.log(this.$refs.myP.innerHTML); // 0
     
          // 解决: this.$nextTick()
          // 过程: DOM更新完会挨个触发$nextTick里的函数体
          this.$nextTick(() => {
            console.log(this.$refs.myP.innerHTML); // 1
          });
     
          //方法二: async 函数执行时, async btn(){}
          //如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,
          //恢复 async 函数的执行并返回解析值
          await this.$nextTick()
          this.$refs.myP.innerHTML
      },

    组件name属性使用 

    我们封装的组件-可以自己定义name属性组件名-让使用者有个统一的前缀风格

    1.给组件(Demo)起个名字,用组件的name属性值, 来注册组件名字

    export default {
      name: "Mmm",
    }

    2.之后就可以用Mmm当作标签使用

    import Demo from "./child/demo";
     
    components: {
        // Demo,
        [Demo.name]: Demo,
      },

    标签: javascript vue

    热门推荐