Vue keep-alive 实战避坑:include/exclude + 路由 meta 标记,中后台路由缓存精准可控|状态管理与路由规范篇
【Vue keep-alive】【中后台路由缓存】从include/exclude控制到路由meta标记彻底搞懂页面缓存可控方案避开组件无name、层级错误等高频坑 文章目录一、先搞清楚为什么要用 keep-alive二、基础用法最简单的 keep-alive2.1 在路由出口处包一层三、include / exclude精确控制「谁缓存、谁不缓存」3.1 参数说明3.2 用 include 做白名单3.3 用 exclude 做黑名单3.4 关键点组件必须有 name3.5 常见坑name 要和 include/exclude 里的完全一致四、路由 meta 标记可维护性更好的方式4.1 路由配置4.2 根据 meta 动态计算 include4.3 Vue 2 中的写法五、更完整的实战结构多级路由 keep-alive5.1 目录结构示例5.2 路由配置5.3 MainLayout.vue 中的 keep-alive5.4 子组件必须定义 name六、生命周期activated 与 deactivated6.1 典型用法刷新列表、恢复滚动七、常见问题与避坑八、推荐规范小结九、小结 系列模块导航同学们好我是 Eugene尤金一名多年中后台前端开发工程师。Eugene 发音 /juːˈdʒiːn/大家怎么顺口怎么叫就好很多前端开发者都会遇到一个瓶颈代码能跑但不够规范功能能实现但维护起来特别痛苦一个人写没问题一到团队协作就各种混乱、踩坑、返工。想写出干净、优雅、可维护的专业代码靠的不是天赋而是体系化的规范 真实实战经验。这一系列《前端规范实战》我会用大白话 真实业务场景不讲玄学、不堆理论只分享能直接落地的规范、标准与避坑指南。帮你从「会写代码」真正升级为「会写优质、可维护、团队级别的代码」。一、先搞清楚为什么要用 keep-alive日常写 Vue 项目时从列表进详情再返回页面会重新渲染数据和滚动位置都会丢失用户体验很差。keep-alive的作用就是把匹配到的组件缓存在内存里切换路由时不会销毁而是保持上一次的状态。再返回时数据、滚动条、表单输入都会保留。适合做缓存的列表页、搜索结果、表单多步骤、数据统计/图表等需要保留状态的页面。不适合缓存的登录页、404、纯静态说明页等。⬆ 返回目录二、基础用法最简单的 keep-alive2.1 在路由出口处包一层!-- App.vue 或根布局组件 --templatedividapprouter-viewv-slot{ Component }keep-alivecomponent:isComponent//keep-alive/router-view/div/template这样写会缓存所有路由组件简单但不可控一般不推荐。⬆ 返回目录三、include / exclude精确控制「谁缓存、谁不缓存」3.1 参数说明参数类型说明includeStringRegExpexcludeStringRegExpmaxNumber最多缓存多少个组件超出按 LRU 策略淘汰这里的「名称」指的是组件的name选项不是路由的path或meta。⬆ 返回目录3.2 用 include 做白名单templaterouter-viewv-slot{ Component }keep-alive:include[ProductList, OrderList, Dashboard]component:isComponent//keep-alive/router-view/template只有name为ProductList、OrderList、Dashboard的组件会被缓存其余不缓存。⬆ 返回目录3.3 用 exclude 做黑名单templaterouter-viewv-slot{ Component }keep-aliveexcludeLoginPage,NotFoundcomponent:isComponent//keep-alive/router-view/templatename为LoginPage、NotFound的组件不会被缓存。⬆ 返回目录3.4 关键点组件必须有 namescriptsetupdefineOptions({name:ProductList// 必须否则 include/exclude 无法匹配})/scripttemplatediv商品列表页/div/template如果组件没有nameinclude/exclude对它是无效的。⬆ 返回目录3.5 常见坑name 要和 include/exclude 里的完全一致// ❌ 错误路由配置里的 component 没有 name{path:/product/list,component:()import(/views/ProductList.vue)}// ProductList.vue 里必须写 defineOptions({ name: ProductList })// ✅ 正确组件 name 和 include 数组里的字符串完全一致// keep-alive :include[ProductList]// ProductList.vue: defineOptions({ name: ProductList })⬆ 返回目录四、路由 meta 标记可维护性更好的方式通过路由的meta标记「是否需要缓存」比在keep-alive里硬编码include数组更清晰也更易维护。4.1 路由配置// router/index.jsconstroutes[{path:/product/list,name:ProductList,component:()import(/views/ProductList.vue),meta:{keepAlive:true}// 标记为需要缓存},{path:/product/detail/:id,name:ProductDetail,component:()import(/views/ProductDetail.vue),meta:{keepAlive:false}// 详情页一般不缓存},{path:/login,name:Login,component:()import(/views/Login.vue),meta:{keepAlive:false}}]⬆ 返回目录4.2 根据 meta 动态计算 include!-- App.vue --templaterouter-viewv-slot{ Component, route }keep-alive:includecachedViewscomponent:isComponent:keyroute.path//keep-alive/router-view/templatescriptsetupimport{computed}fromvueimport{useRouter}fromvue-routerconstrouteruseRouter()// 从路由配置中筛选出 meta.keepAlive true 的组件名constcachedViewscomputed((){returnrouter.getRoutes().filter(routeroute.meta?.keepAliveroute.name).map(routeroute.name)})/script这样只要在路由里改meta.keepAlive就能控制哪些页面被缓存不用再去改keep-alive的配置。⬆ 返回目录4.3 Vue 2 中的写法computed:{cachedViews(){returnthis.$router.options.routes.filter(routeroute.meta?.keepAliveroute.name).map(routeroute.name)}}⬆ 返回目录五、更完整的实战结构多级路由 keep-alive很多项目会区分「有布局的页面」和「无布局的页面」布局里再包一层router-view需要把keep-alive放在正确的层级。5.1 目录结构示例views/ ├── layout/ │ └── MainLayout.vue # 主布局包含侧边栏 内容区 ├── product/ │ ├── ProductList.vue # 商品列表缓存 │ └── ProductDetail.vue # 商品详情不缓存 └── Login.vue # 登录不缓存⬆ 返回目录5.2 路由配置constroutes[{path:/login,component:()import(/views/Login.vue),meta:{keepAlive:false}},{path:/,component:()import(/views/layout/MainLayout.vue),children:[{path:product/list,name:ProductList,component:()import(/views/product/ProductList.vue),meta:{keepAlive:true,title:商品列表}},{path:product/detail/:id,name:ProductDetail,component:()import(/views/product/ProductDetail.vue),meta:{keepAlive:false,title:商品详情}}]}]⬆ 返回目录5.3 MainLayout.vue 中的 keep-alive!-- views/layout/MainLayout.vue --templatedivclassmain-layoutasideclasssidebar.../asidemainclasscontentrouter-viewv-slot{ Component, route }keep-alive:includecachedViewscomponent:isComponent:keyroute.path//keep-alive/router-view/main/div/templatescriptsetupimport{computed}fromvueimport{useRouter}fromvue-routerconstrouteruseRouter()constcachedViewscomputed((){// 只处理当前 layout 下的 children避免把 Login 等算进来constlayoutrouter.getRoutes().find(rr.path/)if(!layout?.children)return[]returnlayout.children.filter(routeroute.meta?.keepAliveroute.name).map(routeroute.name)})/script⬆ 返回目录5.4 子组件必须定义 name!-- ProductList.vue --scriptsetupdefineOptions({name:ProductList})/script⬆ 返回目录六、生命周期activated 与 deactivated被keep-alive缓存的组件不会反复触发mounted/unmounted而是使用activated组件被激活从别的路由切回来时deactivated组件被停用切走时6.1 典型用法刷新列表、恢复滚动scriptsetupimport{ref,onActivated}fromvueimport{useRoute}fromvue-routerconstlistref([])constscrollTopref(0)constrouteuseRoute()// 首次进入或从详情返回都可以在这里刷新onActivated((){loadList()nextTick((){listRef.value?.scrollTo(0,scrollTop.value)})})// 离开时保存滚动位置onDeactivated((){scrollTop.valuelistRef.value?.scrollTop??0})asyncfunctionloadList(){constresawaitfetchList(route.query)list.valueres.data}/script⬆ 返回目录七、常见问题与避坑7.1 缓存了不该缓存的页面现象登录后退出再进登录页还能看到上次的账号。原因登录页被keep-alive缓存了。处理在exclude或meta.keepAlive里排除登录页并确保组件有正确的name。7.2 以为缓存了实际没缓存现象列表页返回后数据丢失。排查组件是否定义了namename是否和include/cachedViews中完全一致keep-alive是否包在了正确的router-view外层多级路由时。7.3 多 Tab 页只缓存一个现象有多个 Tab切换后只保留最后一个的状态。原因多个 Tab 可能共用同一个路由path没有用key区分实例。处理给component加不同的key例如component:isComponent:keyroute.fullPath/这样同一路由的不同参数会当成不同组件实例进行缓存。7.4 缓存的页面需要「按需刷新」可以在meta里加标识或在activated里根据条件决定是否重新请求// 方式1meta 里标记meta:{keepAlive:true,refreshOnActivate:true}// 方式2activated 里判断onActivated((){if(route.query.refresh1){loadList()}})⬆ 返回目录八、推荐规范小结场景建议做法缓存策略用路由meta.keepAlive控制避免在模板里硬编码组件名每个页面组件都定义name且和路由name保持一致keep-alive 位置放在实际渲染页面的router-view外层多级路由时注意层级列表页在activated中按需刷新用deactivated保存滚动位置登录 / 404 等一律meta.keepAlive: false或加入exclude⬆ 返回目录九、小结keep-alive的核心就是三件事include / exclude通过组件name决定缓存范围meta.keepAlive用路由配置统一管理方便维护activated / deactivated在缓存组件里做刷新和状态恢复。记住组件必须写name否则include/exclude不会生效。结合路由meta和生命周期就可以把缓存控制得清晰、可控。⬆ 返回目录 系列模块导航 状态管理与路由规范一、《Vue3 Pinia 状态管理规范状态拆分、Actions 写法、持久化实战避坑状态污染状态管理与路由规范篇》二、《Vue3 Pinia 状态管理规范何时用 Pinia 何时用本地状态状态管理与路由规范篇》三、《Vue Router 实战规范path/name/meta 配置 动态 / 嵌套路由统一团队标准状态管理与路由规范篇》四、《Vue3 Vue Router Pinia 路由守卫规范beforeEach 应做 / 不应做避死循环、防重复请求状态管理与路由规范篇》五、《Vue keep-alive 实战避坑include/exclude 路由 meta 标记中后台路由缓存精准可控状态管理与路由规范篇》 跟着系列慢慢学把技术功底扎扎实实地打牢 系列总览「前端规范实战系列」正在持续更新中后续会整理一篇《前端规范实战系列全系列目录导航》包含每篇文章简介 直达链接方便大家按顺序、体系化学习。更新中敬请期待⬆ 返回目录技术成长从来不是比谁写得快而是比谁写得稳、规范、可维护。哪怕每次只吃透一条规范长期下来差距会非常明显。后续我会持续更新前端规范、工程化、可维护代码相关实战干货帮你告别面条代码、维护噩梦在开发与面试中更有底气。觉得有用欢迎点赞 收藏 关注不错过每一篇实战内容。我是 Eugene与你一起写规范、写优质代码我们下篇干货见
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2440964.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!