You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中mounted早于异步created执行完成触发,如何延迟挂载?

问题原因说明

Vue 的 async 生命周期钩子不会阻塞后续生命周期执行:async created 只是让钩子函数本身返回 Promise,Vue 内部不会等待这个 Promise 执行完成再触发 mounted,所以你会看到日志输出顺序和预期不符,数据返回前挂载的空模板会覆盖 SSR 渲染的内容,导致页面空白。

可行解决方案

方案1:延迟挂载Vue实例(兼容性最好,适合Vue2/Vue3)

先完成数据请求,再初始化Vue实例挂载到DOM,从根源避免空模板覆盖SSR内容的问题,不需要通过props传递数据:

// 原挂载逻辑
/*
import CakeShopList from './CakeShopList.vue'
new Vue({
  render: h => h(CakeShopList)
}).$mount('#cake-shop-list')
*/

// 修改后逻辑
import CakeShopList from './CakeShopList.vue'
// 提前发起数据请求
const fetchCakeShops = (params) => {
  // 你的接口请求逻辑
}

fetchCakeShops({page: 1}).then(cakeShops => {
  // 数据拿到后再实例化Vue并挂载
  new Vue({
    data() {
      return {
        // 把预加载的数据存在根实例,子组件可以直接从根实例取,也可以提前存入Vuex/Pinia
        preloadCakeShops: cakeShops
      }
    },
    render: h => h(CakeShopList)
  }).$mount('#cake-shop-list')
})

子组件内直接读取预加载的数据即可:

// CakeShopList.vue
export default {
  data() {
    return {
      cakeShops: []
    }
  },
  created() {
    // 直接取根实例预加载的数据,不需要等待请求
    this.cakeShops = this.$root.preloadCakeShops
    // 也可以从Vuex/Pinia中取预存的数据
  }
}

方案2:Vue3使用Suspense内置组件

如果是Vue3项目,可以用Suspense包裹异步组件,自动等待异步逻辑执行完成后再渲染组件:

父组件代码

<template>
  <Suspense>
    <template #default>
      <CakeShopList />
    </template>
    <!-- fallback插槽放置SSR渲染的静态内容,加载过程中展示,不会出现空白 -->
    <template #fallback>
      <ul>
        <li>shopA</li>
        <li>shopB</li>
      </ul>
    </template>
  </Suspense>
</template>

子组件代码(使用async setup)

<script setup>
const fetchCakeShops = (params) => {
  // 接口请求逻辑
}
// Suspense会等待这个Promise执行完成再渲染default插槽内容
const cakeShops = await fetchCakeShops({page:1})
</script>

<template>
  <div>
    <ul>
      <li v-for="shop in cakeShops" :key="shop.id" @click="onClickShop(shop.id)">{{shop.name}}</li>
    </ul>
  </div>
</template>

方案3:组件内加载状态切换

如果不想修改挂载逻辑,可以在组件内双模板切换,加载过程中保留静态SSR内容,避免空白:

<template>
  <div>
    <!-- 数据加载完成前展示SSR静态内容 -->
    <ul v-if="!isLoaded">
      <li>shopA</li>
      <li>shopB</li>
    </ul>
    <!-- 数据加载完成后展示动态绑定列表 -->
    <ul v-else>
      <li v-for="shop in cakeShops" :key="shop.id" @click="onClickShop(shop.id)">{{shop.name}}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      cakeShops: [],
      isLoaded: false
    }
  },
  async created() {
    this.cakeShops = await this.fetchCakeShops({page: 1})
    this.isLoaded = true
  }
}
</script>

内容的提问来源于stack exchange,提问作者yasuda_t

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 09:15:03