如何低成本提升用户体验
一、为什么反感传统骨架屏?
我在日常开发中,其实很讨厌骨架屏 —— 因为大部分情况下,这些东西都是在浪费用户的时间,反而增加了用户的等待感知。
后来发现了一个基于 Vue 渲染机制的小巧思,能在仅加载 HTML 阶段就避免空白页面,让用户更快看到反馈。
二、Vue 项目的默认加载痛点
大部分 Vue 项目(无论 Vue2 还是 Vue3),都会有这样的基础结构:
1. 常规 HTML 模板
<!DOCTYPE html>
<html>
<body>
<noscript>
<strong
>We're sorry but <%= webpackConfig.name %> doesn't work properly without
JavaScript enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
</body>
</html>
2. Vue 实例挂载逻辑
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
3. 加载空白问题
页面加载时,用户会先看到空白 —— 直到 Vue 框架、依赖包、业务代码全部加载完成,#app
才会渲染内容,等待感知极强。
三、痛点解决:HTML 阶段提前显示 Loading
核心技巧:在#app
挂载点内部,直接写入静态 Loading 内容。这样用户在加载 JS 之前,就能看到反馈,无需等待 Vue 初始化。
优化后的 HTML 模板:
<!doctype html>
<html>
<body>
<noscript>
<strong
>We're sorry but <%= webpackConfig.name %> doesn't work properly
without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
<!-- 静态Loading:JS加载完成前会显示,挂载后被Vue内容替换 -->
<div class="loading">Loading...</div>
</div>
</body>
</html>
四、进阶:大组件 / 慢渲染场景的优化
如果项目中有体积大、渲染耗时的组件(如复杂表格、富文本编辑器),仅靠 HTML 静态 Loading 不够,此时可结合 Vue3 的 Suspense
(官方文档)和 defineAsyncComponent
(官方文档)实现组件级加载反馈。
其中,defineAsyncComponent
是 Vue3 提供的异步组件定义方法,支持按需加载组件代码,避免大组件阻塞初始渲染;Suspense
是 Vue3 内置组件,专门用于管理异步依赖的加载状态,通过 default
和 fallback
两个插槽分别定义 “加载完成内容” 和 “加载中占位内容”。
1. 实现代码
<template>
<div>
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div class="loading">Loading...</div>
</template>
</Suspense>
</div>
</template>
<script setup>
import { Suspense, defineAsyncComponent } from 'vue'
const AsyncComponent = defineAsyncComponent(() => import('./AsyncComponent.vue'))
</script>
2. 关键优势
加载阶段:显示
fallback
中的 Loading / 骨架屏;完成阶段:自动替换为
AsyncComponent
内容;无需在组件内部写 Loading 逻辑,避免代码冗余;
支持扩展:通过
defineAsyncComponent
的配置项,可添加加载失败重试、延迟加载等进阶功能(详见官方文档)。
五、为什么这是 “最低成本” 方案?
对比其他优化手段(代码压缩、代码分割、CDN 引入、缓存配置、提升带宽),该方案的优势非常明显:
开发成本低:仅需修改 HTML 模板或添加
Suspense
,几行代码即可生效;代码侵入少:不改动核心业务逻辑,仅在 “加载状态层” 做调整;
无额外开销:无需增加基建成本(如 CDN 费用、服务器带宽);
见效快:直接改善用户的加载等待感知,无需复杂配置。
注意事项
截至本文截至时间,Suspense还在Experimental阶段,可能存在变化,具体使用请参考官方文档