vue 之 $nextTick

官方说明:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

疑问:

  1. DOM 更新循环是指什么?
  2. 下次更新循环是什么时候?
  3. 修改数据之后使用,是加快了数据更新进度吗?
  4. 在什么情况下要用到?

原理

   vue的响应式并不是数据发生变化之后DOM立即变化,而是按照一定的方式进行DOM的更新

 

第一个案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
  <div id="app">
    <input type="text" ref="ipt" v-if="isShow" />
    <button @click="fn" v-else>点击修改</button>
  </div>
</template>
 
<script>
 
export default {
  name: "App",
  data() {
    return {
      isShow: false,
    };
  },
  methods: {
    fn() {
      this.isShow = true;
      console.log(this.$refs.ipt);  // undefined      this.$refs.ipt.focus()  //报错
    },
  },
};
</script>
 
<style></style>

 

遇到上述情况怎么解决呢?

1
2
3
this.isShow = true;
setTimeout(() => {
   console.log(this.$refs.ipt); //<input type="text"><br>   this.$refs.ipt.focus()}, 0); <br>//或者 <br>this.$nextTick(() => { <br>   console.log(this.$refs.ipt); //<input type="text"><br>   this.$refs.ipt.focus()});

 

分析:因为  this.isShow = true;时,虚拟dom需要通过diff算法进行更新,这个过程是需要时间的,而同步的代码中,this.$refs.ipt 所需时间 小于  这个渲染时间

 

第二个案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
  <section>
    <h1 ref="hello">{{ value }}</h1>
    <el-button type="danger" @click="get">点击</el-button>
  </section>
</template>
<script>
  export default {
    data() {
      return {
        value: 'Hello World ~'
      };
    },
    methods: {
      get() {
        this.value = '你好啊';
        console.log(this.$refs['hello'].innerText); // Hello World ~
        this.$nextTick(() => {
          console.log(this.$refs['hello'].innerText); // 你好啊
        });
      }
    },
    mounted() {
    },
    created() {
    }
  }
</script>

  

 

应用场景:

    需要在视图更新之后,基于新的视图进行操作

 

思考的问题:$nextTick  如何 结合 created 和 mounted 来处理问题

疑问:

疑问一 . this.$nextTick 为什么要放在 created 或者 mounted ,有什么区别

疑问二 . 为什么$nextTick能保证子组件都加载完?

第一步:了解 created

1
2
3
4
5
6
//组件创建之后
 created() {
      // 可以操作数据,发送ajax请求,并且可以实现
      // vue对页面的影响 应用:发送ajax请求
      console.log('组件创建后:'+this.msg);   //哈哈哈
 }  

 

第二步:了解mounted

1
2
3
4
5
//装载数据到DOM之后
 mounted() {
      // 可以操作DOM
      console.log('DOM装载后:'+document.getElementById('app'));  //<div id="app"><div id="test"></div></div>
 }

 

第三步:分析

疑问一

1.例如在parent 里面有 两个child组件,但是父组件通过异步获取的数据data(created),data里面有childData1 和 childData2 那么此时通过this.$refs.child1是获取不到的,所以需要用到 this.$nextTick,这样可以解决刚才的案例问题(但是,若是同步的组件,那么在parent里面的 mounted 获取 this.$refs.child1也是可以的,那么就不需要该死的this.$nextTick)

2.将this.$nextTict 写在 created 和 mounted 没太大的区别,只是created 会优先 mounted执行,参考 vue 之 生命周期(钩子)

 

疑问二

如果是同步子组件,mounted 就已经能保证了同步子组件都加载完了。因为对于一个页面来说,第一次 DOM 更新循环结束,也就是 mounted 的时候。

同步顺序是 parent created → child created → child mounted → child $nextTick → parent mounted → parent $nextTick

如果是异步子组件,你需要在 mounted 里写 $nextTick,但也并不能完全保证子组件加载完毕,因为异步子组件里还可以再套异步孙子组件。

总而言之,同步子组件,写 created + $nextTick 和写 mounted 都行;异步子组件,除非是在父组件中直接操作异步子组件的生命周期钩子、或者子组件通过 $emit 的方式通知父组件,否则单纯靠父组件自己,是无法百分百保证的。

 

参考:http://errornoerror.com/question/10048646268771205890/

 

posted @   zmztyas  阅读(177)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示