keep-alive+导航守卫让缓存更精确
Posted 空城机
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了keep-alive+导航守卫让缓存更精确相关的知识,希望对你有一定的参考价值。
之前已经写过Vue用keep-alive缓存组件
介绍说明文章,但是还没有实际深入过。然后可以运用的例子就来了。
自己用node
爬虫爬取小说章节,并提供了几个简单的node
数据查询接口。然后制作了一个vue的简易小说阅读器项目(难度并不高,所以界面样式制作时间是最久😖)
组件需缓存分析
在小说阅读器中,只有三个界面:书架
,书籍目录
,章节阅读
这三个界面之间的关系:
实际场景效果:
这三个界面分别是三个vue组件,按照功能的区分,需要使用到keep-alive
进行缓存的界面有两个,分别是书架
和书籍目录
,其中的章节阅读基本每次都要重新刷新
虽然也会有重复点开同一章节的情况,但是先不做考虑,在专门卡bug么
然后对这两个页面需要做的keep-alive
缓存功能也是不同的。
书架
界面:这是主界面,并且基本在第一次加载时所有需要的数据都已经存在,并不存在从书籍目录
切换回来后数据就会改变的情况(虽然以后可能会有未读章节数据改变
),所以直接整个缓存即可。
书籍目录
界面:因为此界面需要获取目录数据可能会较大,如果每次都重新创建,性能消耗过大。如果是点击某一章节看书,看完返回后又重新刷新,不太合适。所以在章节阅读
界面回来后,可以直接keep-alive
加载缓存。但是此时,如果keep-alive
不做处理单纯缓存书籍目录
也会有问题。因为书架
选择不同书,书籍目录
就需要改变。所以此界面需要根据来源页面不同进行缓存加载。
名称 | 不同点 |
---|---|
书架 | 直接加载缓存 |
书籍目录 | 根据不同来源处理缓存 |
最终处理方案
- 首先需要
keep-alive
缓存的组件和不缓存的区分,可以在路由的index.js
文件中组件添加一个keepAlive
属性判断此组件是否需要缓存。
题外话:vue cli中直接用
vue add router
添加路由即可
添加好属性后,可以在主界面中这样写,需要缓存的就会自动被keep-alive
包裹
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
当前的效果:(可以看到书架和书籍目录界面已经缓存了一次,并且之后的切换也不会重新刷新。而阅读章节并不受影响)
- 当前已经做好缓存区分了,并且对于书架来说,缓存的没有问题,那么就要对书籍目录组件单独处理了。 在
vue-router
中,有一个beforeRouteEnter。 这是导航守卫中的组件内守卫,参考链接:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E7%BB%84%E4%BB%B6%E5%86%85%E7%9A%84%E5%AE%88%E5%8D%AB
该导航守卫是在渲染组件的对应路由被验证钱调用,可以使用三个参数:
参数 | 作用 |
---|---|
to | 即将到达的目标,也就是当前要出现页面 |
from | 当前导航要离开的路由,就是上一个页面 |
next | 这时可选参数,因为beforeRouteEnter 内不能获取this, 所以可以通过next(vm => ) 的vm访问组件实例 |
所以可以在书籍目录
组件中添加beforeRouteEnter
beforeRouteEnter: (to, from, next) =>
// // 判断路由来源界面
if (from.name == 'Home' | !from.name)
next(vm=>
// 从书架过来刷新数据
vm.getAllchapterFromApi();
);
else
next();
这样就完成了对应的跳转缓存。
效果:
- 当然,此时会看到如果在
书架
中连续点击两次相同书籍,就会重复刷新,那么这类重复有没有办法解决?
在我的页面跳转时,会有一个书本名称的参数传递,可以根据此来进行判断
错误经历
其实在导航卫士和keep-alive
配合使用过程中,我想试试更多的方式,结果发现都需要书籍目录
组件导航卫士的配合
错误思路1
在书籍目录
组件中可以设置beforeRouteEnter
,那么换位思考,能不能在上一个from的组件中使用beforeRouteLeave
,然后发现在上一个组件中只能通过修改to.meta.keepAlive
来做保证下一个组件不被缓存。
就这样写了:
beforeRouteLeave(to, from, next)
if (from.name == 'Home')
to.meta.keepAlive = false
next()
看上去从书架到目录已经成功了,目录没有缓存。
但是…从章节阅读界面返回到目录时又重新刷新了
这样,可能会想当然的以为在阅读组件中也设置一个反向的to.meta.keepAlive = true
是否可以,但结果是,书籍目录
组件只会缓存第一本,书籍切换后,再返回,加载缓存时的也是第一本。
造成这个结果的原因是,缓存的组件其实本质上并没有进行更新,缓存的还是当初第一本的样子。
错误思路2
在路由index.js文件中使用beforeEnter
进行配置,但是还是和第一种一样,缓存仍未更新
总结
写代码的过程中,其实可以尽可能的将自己学习过的知识点应用出来。虽然有可能一个问题看起来好像有多种写法,但一种种试过去后,就发现自己想当然了。
虽然转牛角尖确实浪费时间,但是要把教训给记录下来,虽然以后自己会忘记,但是文字不会忘。
以上是关于keep-alive+导航守卫让缓存更精确的主要内容,如果未能解决你的问题,请参考以下文章
Vue-Router第三弹-全局导航守卫keep-alive
Vue的钩子函数[路由导航守卫keep-alive生命周期钩子]