defineAsyncComponent 实现路由组件按需加载,核心是封装 import() 为异步组件,仅在路由匹配或首次渲染时触发加载;推荐路由配置中直接使用 () => import() 配合 webpackChunkName 注释实现 code-splitting;手动控制可用 ref + v-if;支持 loading/error 状态但应按需精细控制。
在 setup 中用 defineAsyncComponent 实现路由组件按需加载,核心是把动态 import 封装成异步组件,并确保它只在路由匹配时才触发加载,而不是一进入应用就执行。
不需要额外状态控制,只要用 defineAsyncComponent 包裹 import() 即可。这个组件在首次被渲染(比如路由切换到对应页面)时才真正发起请求:
import { defineAsyncComponent } from 'vue'
const UserPage = defineAsyncComponent(() => import('@/views/UserPage.vue'))
components 选项或返回对象暴露)<UserPage />,但更常见的是配合 <router-view> 自动渲染,无需手动写标签defineAsyncComponent 不是必须的——Vue Router 3.1+ 和 4.x 原生支持函数式 component 写法,Vite/Webpack 会自动做 code-splitting:
component: () => import('@/views/Dashboard.vue')
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue')
适合非路由场景,比如按钮点击后才加载重型编辑器,或 Tab 切换后才拉取子模块:
const Editor = ref(null)
const loadEditor = async () => { Editor.value = (await import('@/components/Editor.vue')).default }
<component :is="Editor" v-if="Editor" />,再用按钮调用 loadEditor()
如果想对某个异步路由组件提供 loading 或 error 提示,可以显式传入配置对象:
const AsyncReport = defineAsyncComponent({
loader: () => import('@/views/Report.vue'),
loadingComponent: { template: '<div>图表加载中...</div>' },
errorComponent: { template: '<div>加载失败,请刷新</div>' },
delay: 300,
timeout: 8000
})