开发应该理清的vue2的生命周期(二)——$nextTick在生命周期的触发时机

开发应该理清的vue2的生命周期(二)

$nextTick在生命周期的触发时机

开始之前,请先认真阅读一下官网关于“nextTick”的内容:

  1. API — Vue.js——Vue.nextTick
  2. API — Vue.js——vm.$nextTick
  3. 深入响应式原理 — Vue.js
  4. API — mounted——注意
  5. API — updated——注意

Vue.nextTick(callback):回调函数callback将在 DOM 更新完成后被调用

本文章,将延续前篇文章[ 开发应该理清的vue2的生命周期(一) ]的测试代码的风格,看看“$nextTick在生命周期的触发时机”。

在本文章,本身组件的<template>标签的主要内容为“<h1 ref=“testRef”>{{ testData }}</h1>”。本组件在“created”和“mounted”生命周期改变了本组件的data值——testData,输出每次改变之前和之后的this.testData的值,同时输出this.$refs.testRef引用的<h1>Dom元素的textContent。且在“created”和“mounted”最后面,再通过使用$nextTick,再输出一遍。加入“beforeUpdate”和“updated”两个生命周期的触发输出。

测试代码

父组件:

// ParentComponent.vue
<template>
  <div>
    <!-- TestNextTickComponent -->
    <TestNextTickComponent/>
  </div>
</template>

<script>
import TestNextTickComponent from "./component/TestNextTickComponent.vue";
export default {
  name: "ParentComponent",
  components: { TestNextTickComponent }
}
</script>

本组件:

// TestNextTickComponent.vue
<template>
  <div class="app-container">
    <h1 ref="testRef">{{ testData }}</h1>
  </div>
</template>

<script>
export default {
  name: "TestNextTickComponent",
  data() {
    return {
      testData: "testData",
    };
  },
  created() {
    console.log("testNextTickComponent created");
    // 输出改变this.testData之前
    console.log(`before created change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
    // 改变this.testData
    this.testData = "testData change on testNextTickComponent created oneself";
    // 输出改变this.testData之后
    console.log(`after created change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent();
    // 在created中,使用$nextTick
    this.$nextTick(() => {
      console.log(`on nextTick (created), this.testData is "${this.testData}"`);
      this.showTestRefDomTextContent();
    });
  },
  mounted() {
    console.log("testNextTickComponent mounted");
    // 输出改变this.testData之前
    console.log(`before mounted change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
    // 改变this.testData
    this.testData = "testData change on testNextTickComponent mounted oneself";
    // 输出改变this.testData之后
    console.log(`after mounted change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent();
    // 在mounted中,使用$nextTick
    this.$nextTick(() => {
      console.log(`on nextTick (mounted), this.testData is "${this.testData}"`);
      this.showTestRefDomTextContent();
    });
  },
  beforeUpdate() {
    console.log("testNextTickComponent beforeUpdate");
  },
  updated() {
    console.log("testNextTickComponent updated");
  },
  methods: {
    // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
    showTestRefDomTextContent() {
      if (!this.$refs.testRef) {
        console.log(`this.$refs.testRef is ${this.$refs.testRef}`);
      } else {
        console.log(`testRefDomTextContent is "${this.$refs.testRef.textContent}"`);
      }
    },
  },
};
</script>

测试结果(添加上注释,便于和测试代码对应,实际输出结果没注释部分):

1. testNextTickComponent created
   // 输出改变this.testData之前
   before created change, this.testData is "testData"
   this.$refs.testRef is undefined
   // 输出改变this.testData之后
   after created change, this.testData is "testData change on testNextTickComponent created oneself"
   this.$refs.testRef is undefined

2. testNextTickComponent mounted
   // 输出改变this.testData之前
   before mounted change, this.testData is "testData change on testNextTickComponent created oneself"
   testRefDomTextContent is "testData change on testNextTickComponent created oneself"
   // 输出改变this.testData之后
   after mounted change, this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent created oneself"

3. testNextTickComponent beforeUpdate
   testNextTickComponent updated
   
4. // 在created中,使用$nextTick
   on nextTick (created), this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"

5. // 在mounted中,使用$nextTick
   on nextTick (mounted), this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"

测试结果分析

  1. testNextTickComponent created
    // 输出改变this.testData之前
    before created change, this.testData is "testData"
    this.$refs.testRef is undefined
    // 输出改变this.testData之后
    after created change, this.testData is "testData change on testNextTickComponent created oneself"
    this.$refs.testRef is undefined
    
    • 本组件的“created”生命周期。testData被赋值了 “testData change on testWatchComponent created oneself”。
    • 由于在created,所以this.$refs.testRef 为 undefined,还不能访问真实Dom。
  2. testNextTickComponent mounted
    // 输出改变this.testData之前
    before mounted change, this.testData is "testData change on testNextTickComponent created oneself"
    testRefDomTextContent is "testData change on testNextTickComponent created oneself"
    // 输出改变this.testData之后
    after mounted change, this.testData is "testData change on testNextTickComponent mounted oneself"
    testRefDomTextContent is "testData change on testNextTickComponent created oneself"
    
    • 现在到本组件的“mounted”生命周期。testData被赋值了 “testData change on testWatchComponent mounted oneself”。

    • 由于已经在mounted,所以this.$refs.testRef 不为 undefined,可以访问真实Dom。在mounted里改变this.testData之前和之后,都访问到<h1>Dom元素的textContent为在created设置的新值——“testData change on testWatchComponent created oneself”。

    • 这时你可能会问,“假如本组件在created函数中,没将testData赋值 "testData change on testWatchComponent created oneself"呢?”

      更改如下:

        created() {
          console.log("testNextTickComponent created");
          // // 输出改变this.testData之前
          // console.log(`before created change, this.testData is "${this.testData}"`);
          // this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
          // // 改变this.testData
          // this.testData = "testData change on testNextTickComponent created oneself";
          // // 输出改变this.testData之后
          // console.log(`after created change, this.testData is "${this.testData}"`);
          // this.showTestRefDomTextContent();
          // 在created中,使用$nextTick
          this.$nextTick(() => {
            console.log(`on nextTick (created), this.testData is "${this.testData}"`);
            this.showTestRefDomTextContent();
          });
        },
        mounted() {
          console.log("testNextTickComponent mounted");
          // 输出改变this.testData之前
          console.log(`before mounted change, this.testData is "${this.testData}"`);
          this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
          // 改变this.testData
          this.testData = "testData change on testNextTickComponent mounted oneself";
          // 输出改变this.testData之后
          console.log(`after mounted change, this.testData is "${this.testData}"`);
          this.showTestRefDomTextContent();
          // 在mounted中,使用$nextTick
          this.$nextTick(() => {
            console.log(`on nextTick (mounted), this.testData is "${this.testData}"`);
            this.showTestRefDomTextContent();
          });
        },
      

      通过测试,输出的结果如下。

      1. testNextTickComponent created
      
      2. testNextTickComponent mounted
         // 输出改变this.testData之前
         before mounted change, this.testData is "testData"
         testRefDomTextContent is "testData"
         // 输出改变this.testData之后
         after mounted change, this.testData is "testData change on testNextTickComponent mounted oneself"
         testRefDomTextContent is "testData"
      
      3. testNextTickComponent beforeUpdate
         testNextTickComponent updated
         
      4. // 在created中,使用$nextTick
         on nextTick (created), this.testData is "testData change on testNextTickComponent mounted oneself"
         testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"
      
      5. // 在mounted中,使用$nextTick
         on nextTick (mounted), this.testData is "testData change on testNextTickComponent mounted oneself"
         testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"
      

      可以看到,重点为第2条发生了变化,在mounted里改变this.testData之前和之后,都访问到<h1>Dom元素的textContent为testData的默认值——“testData”。

  3. testNextTickComponent beforeUpdate
    testNextTickComponent updated
    
    • 由于在“mounted”生命周期,testData改变了,所以Dom 被更新——触发了“beforeUpdate”和“updated”

    • 这时你可能会问,“假如本组件在mounted函数中,没将testData赋值 "testData change on testWatchComponent mounted oneself"呢?“beforeUpdate”和“updated”还会触发吗?”
      更改如下:

        created() {
          console.log("testNextTickComponent created");
          // 输出改变this.testData之前
          console.log(`before created change, this.testData is "${this.testData}"`);
          this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
          // 改变this.testData
          this.testData = "testData change on testNextTickComponent created oneself";
          // 输出改变this.testData之后
          console.log(`after created change, this.testData is "${this.testData}"`);
          this.showTestRefDomTextContent();
          // 在created中,使用$nextTick
          this.$nextTick(() => {
            console.log(`on nextTick (created), this.testData is "${this.testData}"`);
            this.showTestRefDomTextContent();
          });
        },
        mounted() {
          console.log("testNextTickComponent mounted");
          // 输出改变this.testData之前
          // console.log(`before mounted change, this.testData is "${this.testData}"`);
          // this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
          // // 改变this.testData
          // this.testData = "testData change on testNextTickComponent mounted oneself";
          // // 输出改变this.testData之后
          // console.log(`after mounted change, this.testData is "${this.testData}"`);
          // this.showTestRefDomTextContent();
          // 在mounted中,使用$nextTick
          this.$nextTick(() => {
            console.log(`on nextTick (mounted), this.testData is "${this.testData}"`);
            this.showTestRefDomTextContent();
          });
        },
      

      通过测试,输出的结果如下。

      1. testNextTickComponent created
         // 输出改变this.testData之前
         before created change, this.testData is "testData"
         this.$refs.testRef is undefined
         // 输出改变this.testData之后
         after created change, this.testData is "testData change on testNextTickComponent created oneself"
         this.$refs.testRef is undefined
      
      2. testNextTickComponent mounted
         
      3. // 在created中,使用$nextTick
         on nextTick (created), this.testData is "testData change on testNextTickComponent created oneself"
         testRefDomTextContent is "testData change on testNextTickComponent created oneself"
      
      4. // 在mounted中,使用$nextTick
         on nextTick (mounted), this.testData is "testData change on testNextTickComponent created oneself"
         testRefDomTextContent is "testData change on testNextTickComponent created oneself"
      

      可以看到,假如本组件在mounted函数中,没将testData赋值 "testData change on testWatchComponent mounted oneself"时,“beforeUpdate”和“updated”没被触发。

      在“mounted”之后,在created中和mounted中使用的$nextTick的回调函数依次被调用了

  4. // 在created中,使用$nextTick
    on nextTick (created), this.testData is "testData change on testNextTickComponent mounted oneself"
    testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"
    
    • 可以看到,在“updated”之后,在created中使用$nextTick的回调函数被调用了。
    • 访问到<h1>Dom元素的textContent为在mounted设置的新值——“testData change on testNextTickComponent mounted oneself”。
  5. // 在mounted中,使用$nextTick
    on nextTick (mounted), this.testData is "testData change on testNextTickComponent mounted oneself"
    testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"
    
    • 可以看出,同样在“updated”之后,在mounted中使用$nextTick的回调函数被调用了,结果和“在created中使用$nextTick的回调函数被调用”的一致。

进一步思考

现在,你可以将三种情况下的测试结果(①created和mounted都更改testData;②仅created更改testData;③仅mounted更改testData)再进行一次比较,你将会更清楚“$nextTick在生命周期的触发时机”

现在,假如在created上模拟一次请求,然后更改this.testData,created函数更改如下:

created() {
    console.log("testNextTickComponent created");
    // 输出改变this.testData之前
    console.log(`before created change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent(); // 输出this.$refs.testRef引用的<h1>Dom元素的textContent
    // 改变this.testData
    this.testData = "testData change on testNextTickComponent created oneself";
    // 输出改变this.testData之后
    console.log(`after created change, this.testData is "${this.testData}"`);
    this.showTestRefDomTextContent();
    // 在created中,使用$nextTick
    this.$nextTick(() => {
      console.log(`on nextTick (created), this.testData is "${this.testData}"`);
      this.showTestRefDomTextContent();
    });
    
    // 新添加
    // 模拟请求,然后更改this.testData
    setTimeout(() => {
      this.testData = "testData change on setTimeout (created)";
      // 输出模拟请求后,改变this.testData之后,但不在使用$nextTick中
      console.log(`on setTimeout (created and setTimeout), this.testData is "${this.testData}"`);
      this.showTestRefDomTextContent();
      // 输出模拟请求后,改变this.testData之后,同时在使用$nextTick中
      this.$nextTick(() => {
        console.log(`on setTimeout (created 、setTimeout and nextTick), this.testData is "${this.testData}"`);
        this.showTestRefDomTextContent();
      });
    }, 5000);
  },

结果为:

先输出最开始的那个测试结果。

1. testNextTickComponent created
   // 输出改变this.testData之前
   before created change, this.testData is "testData"
   this.$refs.testRef is undefined
   // 输出改变this.testData之后
   after created change, this.testData is "testData change on testNextTickComponent created oneself"
   this.$refs.testRef is undefined

2. testNextTickComponent mounted
   // 输出改变this.testData之前
   before mounted change, this.testData is "testData change on testNextTickComponent created oneself"
   testRefDomTextContent is "testData change on testNextTickComponent created oneself"
   // 输出改变this.testData之后
   after mounted change, this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent created oneself"

3. testNextTickComponent beforeUpdate
   testNextTickComponent updated
   
4. // 在created中,使用$nextTick
   on nextTick (created), this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"

5. // 在mounted中,使用$nextTick
   on nextTick (mounted), this.testData is "testData change on testNextTickComponent mounted oneself"
   testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"

然后,大概过个5秒左右,再输出以下结果

6. // 输出模拟请求后,改变this.testData之后,但不在使用$nextTick中
   on setTimeout (created and setTimeout), this.testData is "testData change on setTimeout (created)"
   testRefDomTextContent is "testData change on testNextTickComponent mounted oneself"

7. testNextTickComponent beforeUpdate
   testNextTickComponent updated
   
8. // 输出模拟请求后,改变this.testData之后,同时在使用$nextTick中
   on setTimeout (created 、setTimeout and nextTick), this.testData is "testData change on setTimeout (created)"
   testRefDomTextContent is "testData change on setTimeout (created)"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值