Keep-alive
vue2.0中提供了一个keep-alive
的组建来缓存组件,避免多次加载相应的组件,减少性能消耗。
keep-alive是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM,结合vue-router中使用。可以缓存某个view的整个内容。
语法:
复制代码
一般有这种需求的都是,第一次进入页面时请求一次数据,后面通过路径切换或者前进/后退进入改页面时,页面都使用的缓存数据,DOM不会刷新。
prop
- include: 字符串或正则表达式。只有匹配的组件会被缓存。
- exclude: 字符串或正则表达式。任何匹配的组件都不会被缓存。
条件缓存 【prop】
export default { name: 'test', data() { return { includedComponents: 'test' } }}复制代码
结合exclude和include来进行条件缓存
复制代码
部分缓存【keepAlive属性】
我们可能会碰到这样的需求,部分缓存:
主页 - 列表页 - 详情页主页 => 列表页 【列表页不需要缓存】详情页 => 列表页 【列表页需要缓存】复制代码
网上有很多关于这个例子的解决方案,但是大家有没有发现这种处理方法存在问题,代码大概是这样的。
复制代码
list页面路由
{ path: '/list', name: 'list', component: list, meta: { keepAlive: true, } }复制代码
Home页面设置
export default { data() { return {}; }, methods: {}, beforeRouteLeave(to, from, next) { // 设置下一个路由的 meta to.meta.keepAlive = false; // Home 跳转到 list 时,让 list 不缓存,即刷新 next(); }};复制代码
detail页面
export default { data() { return {}; }, methods: {}, beforeRouteLeave(to, from, next) { // 设置下一个路由的 meta to.meta.keepAlive = true; // detail 跳转到 list 时,让 list 缓存,即不刷新 next(); }}; 复制代码
这种方案的bug:
- 首次从 Home => list[页面刷新] => detail;
- 目前我们处于detail页面;
- detail => list[页面刷新] 【为什么呢?因为我们在Home =>list时将list的keepAlive设置为false了】;
- 当前处于list页面,
- 再次从 list => detail ,然后返回 detail => list[页面没有刷新],缓存成功。
也就是说只要从 Home => list,list的缓存设置失效,必须经历一次detail => list 才能将keepAlive设置为true,list才能达到缓存效果。
结合Keep-alive实现复杂缓存
今天想说的重点 最近有一个需求是这样的:
A_1 => A [A页面需要缓存]B_1 => B [B页面需要缓存]A => B [B不需要缓存]B => A [A不需要缓存]复制代码
这种需求怎么实现呢?最开始的想法是更改keepAlive的方式,最后发现行不通。最后的解决方案是
- 将A,B页面设置为缓存页面
- 记录页面的跳转,即上一个页面是哪一个。
- 在A,B页面中判断上一个页面不是A_1或者B_1是就手动刷新页面【activated】阶段,因为页面缓存后第二次进入是不会进入created和mounted的。
具体代码: 路由设置
{ path: '/A', name: 'A', component: A, meta: { keepAlive: true, } }, { path: '/B', name: 'B', component: B, meta: { keepAlive: true, } }复制代码
main.js中记录上一个路由地址
router.beforeEach((to, from, next) => { Vue.prototype.beforeRouter = from; next();})复制代码
A.vue页面,
activated() { const beforeRouterName = this.beforeRouter.name; if (beforeRouterName && beforeRouterName !== 'A_1') { // 手动刷新页面 this.$refs.table.reload(); } },复制代码
B.vue页面
activated() { const beforeRouterName = this.beforeRouter.name; if (beforeRouterName && beforeRouterName !== 'B_1') { // 手动刷新页面 this.$refs.table.reload(); } },复制代码
这样就可以实现只要不是B_1/A_1页面进入到B/A时都可以将页面刷新。可能不是最好的解决方案,
如果你有什么更好的解决方法可以留言; 查看更多相关信息可关注公众号: