Vue 踩坑:async mounted 方法和父子组件mounted方法的执行顺序

3,412 阅读1分钟

问题背景:项目中列表有两个版本,显示哪一个取决于接口返回的配置。在项目入口 App.vue 的 mounted 方法中请求配置数据 IsBetaList,放进store 中,IsBetaList 在 store 中默认是 false。在 App.vue 的子组件 list.vue 中 根据 IsBetaList 来决定是采用新版列表还是旧版列表。实际中发现始终渲染旧版列表。

父组件的 mounted 方法

  async mounted() {
    await new Promise(function (resolve) {
      setTimeout(() => {
        resolve(true);
      }, 500);
    }).then((res) => {
      this.$store.commit("SetListVersion", res);
    });
  }

子组件的 mounted 方法

  @State('isBetaList') isBetaList;

  mounted() {
    if (this.isBetaList) {
      new Vue({
        el: '#about',
        render(h) {
          return h('div', {
            domProps: {
              innerText: '新版列表'
            }
          });
        }
      });
    } else {
      new Vue({
        el: '#about',
        render(h) {
          return h('div', {
            domProps: {
              innerText: '旧版列表'
            }
          });
        }
      });
    }
  }

执行顺序

  • 第一步:执行子组件 mounted 方法中的同步部分。根据 isBetaList 来创建新列表或者旧列表。但此时,isBetaList 还是默认值 false,所以创建旧列表。挂载成功后。
  • 第二步:执行父组件 mounted 方法中的同步部分。then(...)属于异步部分。
  • 第三步:执行父组件 mounted 方法中的异步部分。将isBetaList的值设置成 true。但是子组件的 mounted 方法只执行一次。 所以看到的始终是旧版列表。