ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

若依框架页面缓存不生效?keep-alive配置与tab切换状态保持实战解析

若依框架页面缓存不生效?keep-alive配置与tab切换状态保持实战解析 切换页面就刷新数据、表单填到一半切个tab回来全没了这个问题在若依这类后台管理系统里太常见了。搞过vue-element-admin系项目的人应该都有印象明明页面只是切走了一下再回来路由变了、组件重建了、接口重新打了一遍体验特别割裂。若依本身封装了不少东西很多初学者根本不知道在哪一步控制缓存甚至不知道有keep-alive这回事。这篇文章专门把这个点彻底拆开讲透从原理到配置再到踩坑一次说清楚。1. 内容整体设计与思路拆解1.1 需求场景分析为什么切换tab不重新加载这么重要后台管理系统和面向C端的网站有个很大的区别后台页面往往不是简单的浏览型页面而是操作型页面。用户可能正在填写一个几十个字段的表单可能在列表页设置了复杂的筛选条件可能打开了某个详情页正在比对数据。这个时候切到另一个菜单或者标签页处理别的事情再切回来如果页面状态全部丢失那体验就是灾难级的。具体到若依这种框架它基于vue-element-admin改造而来本身带了tab页签TagsView的功能。正常情况下通过在路由meta上标记keepAlive字段配合 组件就能实现页面缓存。但实际用的时候你会发现有时候配了不生效有时候缓存了但数据是旧的有时候页面挂了报错问题非常多。这篇文章就是来把这些问题的根源、机制、解法全部理清楚。1.2 核心机制解析keep-alive到底做了什么在聊具体配置之前先把底层机制搞明白。Vue的 是一个内置抽象组件它的作用是在组件切换过程中把状态保留在内存里而不是销毁重建。默认情况下路由切换时组件实例会被销毁所有data、dom状态、滚动位置全部清空下次进入重新走一遍created、mounted生命周期。而用了keep-alive之后被包裹的组件在切换时会被缓存起来再次显示时不会重新走创建流程而是直接复用已有的实例。keep-alive有两个重要属性include和exclude。include支持字符串、正则表达式或数组匹配的是组件的name选项。只有匹配上的组件才会被缓存没匹配上的该销毁还是销毁。这个匹配组件name的机制是整个方案的关键点后面几乎所有奇奇怪怪的问题最终都指向这里。在若依项目中AppMain.vue里的主体内容区域通常长这样router-view v-slot{ Component } keep-alive :includecachedViews component :isComponent :keygetRouteKey(route) / /keep-alive /router-view这里的cachedViews是一个数组里面存的是需要缓存页面的组件name。这个数组是怎么来的通常是在permission.js或者store/modules/tagsView.js里遍历路由配置把meta.keepAlive为true的路由对应的组件name收集起来存到Vuex里。若依原本的代码里这部分逻辑相对隐蔽很多人根本不知道要去配所以默认情况下所有页面都是不缓存的切tab就重新加载。1.3 组件name与路由name的对应关系前面说了keep-alive的include匹配的是组件的name所以组件name和路由name的一致性就变成了整个方案能否生效的分水岭。若依的页面组件通常写在src/views/xxx/index.vue里面组件导出的时候要设置namescript export default { name: UserManage, data() { return {} } } /script而路由配置在router/index.js里{ path: /system/user, component: Layout, redirect: /system/user/index, children: [ { path: index, name: UserManage, component: () import(/views/system/user/index.vue), meta: { title: 用户管理, keepAlive: true } } ] }这里一个非常容易踩的坑出现了路由的name和组件的name必须一致而且这个一致是严格一致包括大小写。如果路由name写的是UserManage组件name写的是UserManage那没问题。但如果你只改了路由name、忘了改组件里export default的name或者两者大小写不一致keep-alive的include匹配就会失败缓存不生效页面照样重新加载。为什么需要一致因为include数组里存的是路由meta标记后收集出来的name值vue拿到这个值去和组件的name做匹配。如果组件name和路由name对不上就会出现我明明配置了keepAlive: true怎么还是不缓存这种鬼问题。1.4 为什么切tab会重新加载梳理若依的默认行为其实从代码层面看若依在标签页TagsView上的实现本身就包含了缓存的联动逻辑。在src/store/modules/tagsView.js里有一个addView方法它会判断当前路由的meta.keepAlive是否为true如果为true就把组件的name塞进cachedViews数组。然后AppMain里面的include拿到这个数组去控制具体哪些页面组件被keep-alive缓存。但这里面有个非常重要的前提你的路由meta必须正确配置了keepAlive字段且值为true。很多人的问题恰恰出在这里。若依的菜单是动态生成的通过后端返回的路由配置来动态添加路由前端的meta信息有些是静态写死的有些是在动态路由处理逻辑里拼接的。如果你加了一个新页面但忘了在meta里加keepAlive: true那它天然就不会被缓存切走再切回就重新加载。这不是bug是设计如此。另外一个隐性问题如果你配置了keepAlive: true但没有激活缓存还有一种可能是因为你的页面组件根本没有设置name。包括之前说的如果组件用的是Vue3的
返回列表