上午十点,群里的 @全体成员 比咖啡醒脑:“切个 Tab,接口怎么齐步走两次?卡得像喉咙里有痰。” 我瞄了眼 Network,两条请求并排躺着,姿势整齐,像我刚才心里默念的 “KeepAlive 应该很懂事啊” 被人当场打脸。
那几天没少跟框架斗心眼,我干脆把告警原文、父组件两段模板、文档里 KeepAlive 关键词揉成一页备忘丢给常用模型:别灌鸡汤,按优先级列可能路径,每条附上怎么证伪。 十分钟拿回一张还算干净的拓扑——`:is`、缓存 key、竞态……像有人先把白板擦了,我只用往上写第一层。
它有边界:不会替你在线上呼吸。 训练里学的是 “下文怎么接才像人写的”;你再塞点 changelog,只是把胡扯空间收窄。路线图可以快出,章还得自己盖。
下面是跟同事、跟文档、跟两次源码对过眼之后的版本;上面那段顶多算开场锣鼓。
一、案发现场:双倍请求不是灵异事件
首页两个 Tab:“门票 Ticket” 和 “周边 Life”。初代写法很克制,也很天真:
<!-- 父组件容器 -->
<KeepAlive>
<component :is="activeTab === 'ticket' ? Ticket : Life" />
</KeepAlive>我心想:包了 `KeepAlive`,实例怎么也得像长住客,顶多出门抽根烟。结果一切 Tab,子组件跟第一天入职似的重新 onMounted。 请求写在这里?来都来了,再薅一把。
那一刻我才听懂用户说的 “卡”:不一定慢在动画,可能慢在接口带薪加班。
二、把锅扶稳:缓存到底在缓存谁
这部分不装读过十万行 runtime,只写我和文档对齐之后的结论:
换的是组件类型,不是 “幕布后拎人”。 A、B 两个定义轮流上,卸载再挂载是默认套餐,不等于先把实例藏屏风后面。
KeepAlive 也挑活。 不是冻龄精华抹一脸就完事;类型交替上场,语义更接近 “换剧本”,生命周期该排的队还会排。
onMounted 是扩音器。 钩子多跑几次,它就老实多干几次活——不读空气,只读调用。
指望 “KeepAlive + 不同类型 `:is`” 自动替你省心,多半属于 健身卡式自我感动:卡办了,泳圈也可能涨了。
三、改法不玄学:v-show + 业务 key
就一句:Tab 只是躲猫猫,用样式糊弄;真要换世界观,再上 key。
1. 父组件:握紧遥控器
<!-- index.vue -->
<script setup>
const refreshKey = ref(0); // “业务户口本”版本号,别没事加一
const homeStore = useHomeStore();
watch(() => homeStore.getSocialRegionId(), (newId, oldId) => {
if (newId && oldId && newId !== oldId) {
// 换城市这种硬变更,才配叫推倒重来
refreshKey.value++;
}
});
</script>
<template>
<!-- v-show:人还在工位,只是暂时 unseen -->
<Ticket v-show="activeTab === 'ticket'" :key="`ticket-${refreshKey}`" />
<Life v-show="activeTab === 'life'" :key="`life-${refreshKey}`" />
</template>2. 子组件:别当全频段收音鸡
能挪出 mounted 的拉数,就往 props 或明确的刷新信号那儿挪。
Store 监听漫天飞的,调试时群里艾特它比艾特谁都快——让它做回安静同事比较积德。
四、收工前的几句人话
KeepAlive 不是万金油。 列表进详情那种深度往返它很香;同级 Tab 高频互瞟,多半是 v-show 更老实。
`onMounted` 像进场,`onActivated` 像又回台前(真跟 KeepAlive 过日子的时候别念混)。念混了,控制台里接口能凑一桌麻将。
模型能提速,不能替你签字。 假设挨个撞证据,比撞上 “感觉对了” 更有用。
收工说句俗的:重复请求少了,告警群安静得我反而不踏实。框架有脾气,模型很会猜脾气,线上背锅的是你。 不押韵,够跟下一个通宵的自己碰个杯。
本文属于 AI 实用主义流派 的第 4 篇肉身实战。
发表评论
分享你的想法和反馈