Vue应用created钩子发请求时静态元素提前加载显示空内容如何解决
问题根因
Vue的生命周期执行流程不会等待异步操作完成再推进后续步骤。你在created钩子中调用的getData是异步请求方法,调用后会立即返回,不会阻塞组件的渲染流程,因此组件会优先使用初始值为空数组的fetchedData完成首次渲染,等请求响应返回更新fetchedData后才会触发二次渲染更新页面内容,这就是你看到先显示长度为0的本质原因。
可选解决方案
添加加载状态占位(兼容性最好,Vue2/Vue3通用)
新增加载状态变量控制页面渲染逻辑,请求过程中显示加载提示,请求完成后再显示实际内容,代码修改参考如下:<template> <div id="app"> <!-- 加载状态提示 --> <div v-if="isLoading">数据加载中...</div> <!-- 实际内容,加载完成后显示 --> <template v-else> <h1>My Data length: {{fetchedData.length}}</h1> <li v-for="value in fetchedData" :key="value">{{value}}</li> </template> </div> </template> <script> export default { name: "MyVueComponent", data() { return { fetchedData: [], isLoading: false // 新增加载状态 } }, methods: { async getData() { this.isLoading = true try { const response = await fetch('https://cli-vue-application.herokuapp.com/user/getUser', { method: 'POST', headers: { 'Content-Type': 'application/json' }, }) const data = await response.json() this.fetchedData = data } catch (err) { // 可自行添加请求失败的处理逻辑 console.error('数据请求失败', err) } finally { this.isLoading = false } } }, created() { this.getData(); } } </script>同时你的原有代码混用了
async/await和then链式调用,上述优化后的写法更简洁,也不需要额外绑定this指向。使用Suspense组件(仅Vue3适用)
如果你使用Vue3,可以用内置的Suspense组件包裹你的业务组件,在fallback插槽中定义加载占位内容,框架会自动在异步组件的异步逻辑执行完成后再渲染实际内容。路由级预加载(使用VueRouter时适用)
可以通过路由的beforeEnter守卫,或者组件的beforeRouteEnter钩子,在进入对应路由前就发起数据请求,等数据获取完成后再推进路由跳转、渲染组件,完全避免空内容的闪现。
内容的提问来源于stack exchange,提问作者egx
相关产品推荐
相关产品推荐

