动态组件、KeepAlive、异步组件,和那个「拿不到子组件方法」的坑

① 用 <component :is="名字" /> 在三个组件之间切换,而不是写一串 v-if; ② 切走的时候到底是「卸载」还是「进缓存」,由 <KeepAlive> 说了算; ③ 慢组件交给 defineAsyncComponent,加载态和超时态都有专门的组件来显示; ④ 子组件默认对父级封闭,想让它的方法能被 ref 调用,必须点名暴露出去。

一句话记住::is 用组件名,切换只改一个字符串,配合 KeepAlive 才谈得上「缓存了哪个」; KeepAlive 只认 name,include / exclude 拿 name: 'tab-a' 去比对,而且缓存 ≠ 暂停,副作用要在 onActivated / onDeactivated 里自己管; 异步组件四个态:delay 内静默 → loading → 成功内容 / 超时 errorComponent,重试得换一个新对象; ref 不是后门,父级只能调到子组件点名暴露出来的方法。

速查:KeepAlive 的 props / 两套生命周期 / 异步组件的选项

东西怎么写注意点
include / exclude<KeepAlive include="tab-a">,也可以传数组或正则按组件的 name 匹配,不是按标签名;这里每个 tab 都显式写了 name: 'tab-a'。两个都不写 = 全缓存
max<KeepAlive :max="10">缓存上限,超了按最近最少使用踢掉一个,别拿它当内存泄漏的解药
onActivated / onDeactivated只在 KeepAlive 里触发不包 KeepAlive 时走的是 onMounted / onUnmounted;缓存期间 setInterval 这类副作用并没有停,要在 onDeactivated 里自己停
defineAsyncComponent{ loader, loadingComponent, errorComponent, delay, timeout }loader 返回 Promise;delay(默认 200ms)之内不闪 loading;timeout 不写就永不超时;同一个异步组件对象会缓存结果,重试要重建它或用 onError;交给 :is 之前存进 shallowRef 而不是 ref
defineExpose / expose<script setup> 里 defineExpose({ publicMethod });Options 写 expose: ['publicMethod']<script setup> 的组件默认封闭,父级 ref 只能拿到你点名暴露的成员;Options API 不写 expose 则整个实例敞开
[迷你控制台] Vue 开发版的警告会同时显示在这里和浏览器控制台