1.需求
在项目开发中,前端难免遇到需要路由缓存的需求。在之前一个React
项目中,查询各种资料和插件后,了解到React
要配合React-router
进行路由缓存,会有很多意想不到的问题。所以在React
项目中,我们都避免接收到需要路由缓存的需求。
最近在开发一个vue
项目中,由于vue
原生有Keep-alive
组件以及include
,exclude
的各种api
来实现路由缓存。所以我们决定大胆的接下这个坑。
2.踩坑
一开始我们也是直接用keep-alive
包裹住router-view
加上路由的fullPath
作为router-view
的key
值,然后用include
定义需要缓存的组件。
以及在路由定制的meta
里面定义keepalive
是否需要缓存字段来处理缓存
对于一般的项目,其实这样解决缓存已经可以了。但是我们是对应B端的管理系统,会有菜单页,Tab页,一个路由可能在不同的情况会需要缓存以及不需要缓存两种情况。在动态改变keepaliveList
或者$route.meta.keepalive
后,并没有触发组件缓存的销毁以及再缓存。所以我们只能变换方法来实现。
3.解决思路--清理详情页缓存
我们的项目会有多个Tab的形式,类似于element-ui
的tabs组件。
我们在相同tab下的路由配置了相同的pageKey
代表在一个tab下的路由组件。
按照上面的配置,组件A,B是在一个tab下,C是在另一个tab下的。
在用keep-alive
包裹住router-view
后,可以实现切换不同tab,切换路由,缓存页面,但是在同一个tab下从列表跳到详情页,我们需要详情页每次进入都需要清楚缓存重新查询数据。介于有这两种需要不同缓存效果的组件,我们在路由定义时多加了一个noCache
字段,定义了这个字段的路由,表明在不同pageKey路由(表示不同tab)之间切换时,需要缓存,在相同pageKey(表示同一tab)路由之间切换时,不需要缓存并清理。
在查询资料后,了解到vue把缓存组件存储到$vnode.parent.componentInstance.cache
中,我们想到了一个用vue路由钩子清理缓存的一个方法。
以上代码是在第一次打开详情页返回到列表页时,进入beforeRouteLeave
钩子函数,调用clearCache
方法清除详情页的缓存。
4.解决思路--关闭tab清理缓存
现在还有一个问题是每个tab会有关闭按钮,在点击一个tab的关闭按钮后,应该清除该tab同一个pageKey
的所有组件缓存。这里我们在点击关闭按钮事件中设置vuex
全局变量在全局beforeRouteLeave
的判断里加上该判断,如果全局变量变化说明点击了关闭按钮,然后再clearCache
方法内部清除相同pageKey
的组件cache
列表。
5.解决思路--返回列表缓存查询条件并重查数据
到这里其实大部分的缓存问题已经解决了,但是我们可爱的产品爸爸,突然给我们提了一个新的需求,在详情页跳转到列表页的时候,需要列表页的查询条件存在,并且重查一次查询。刚开始我们决定考虑新的解决思路来清理列表页的缓存,并且存储下列表页的查询条件。由于我们列表页不会设置noCache
字段,所以查询列表的条件缓存是存在的,我们只需要重新调一次查询接口就可以了。
根据这个思路,我们在详情页跳转回列表页时给详情页meta
对象新增一个backSearch
字段,在beforeRouteLeave
中如果捕获到from.meta.backSearch
,则删除这个属性并且设置to.meta.backSearch=true
,再设置一个全局actived
缓存钩子如果检测到该路由的meta.backSearch
字段,则自动调用组件定义的myOption
方法实则为该组件的查询方法
6.解决思路--url随机数清理缓存
以上大概解决了业务提的所有缓存需求。但是在最近的开发中,由于用户的骚操作,又爆发出了缓存的又一bug。
我们清理详情页缓存的触发条件是,相同pageKey
之间跳转的情况,例如详情页跳转回列表页,但是用户的一次操作是进入了详情页直接点击菜单进入了其他页面,然后点列表菜单重新进入列表页,路由全在不同pageKey
的情况下跳转,并没有触发详情页缓存逻辑。
在注意到我们的router-view
key
字段是$route.fullPath
,所以我们决定给url
加上随机数来解决这个问题。
7.结语
目前我没找寻到一个业界比较公认的缓存解决办法,我们也在探索之中。我们的方法可能比较繁琐,但目前能解决我们的开发需求,如果有大佬能给我们提一些宝贵的意见,我们会非常感谢。