作者:waker

前言

业务里常常有这样的需要, 页面跳转的时候放弃前一个页面的状态跟数据, 不便返回时解决
例如: A->B须要缓存, A->C不须要缓存
网上大部分例子都须要去解决业务组件, 感到十分不合理
故本人分享改性能用来解决此类问题

vue的keepAlive组件很适宜解决这类问题, 但还是有缺点, 比方很难灵便的依据路由来管制是否须要缓存, 只能简略的通过include来匹配是否须要缓存

整顿后需要如下:

1. 组件须要在局部页面缓存,脱离了这部分页面则清理缓存2. 组件须要在全局缓存3. 最好从架构层面解决,不要干预业务组件

大抵思路

在路由meta里增加keealive:['路由的name'],确定失效的作用页面
设置一个store来绑定keepalive
在全局路由钩子里对该store解决

代码如下

路由meta里设置keepAlive,示意拜访这些页面须要缓存组件

// 路由配置{    path: 'xxx',    name: 'xxx',    component: () => import('xxx'),    meta: {        title: 'xxx',        keepAlive: ['路由name', 'b'],//作用域:缓存在这些页面留存    },},

在store里设置keepAliveIncludes用来绑定keepAlive

// vuex 设置跟删除缓存组件state: {    keepAliveIncludes:[] },mutations: {    // 设置缓存    SET_KEEPALIVEINCLUDES: (state, data) => {      const has = state.keepAliveIncludes.find(i=>i.path === data.path)      if(!has){        state.keepAliveIncludes.push(data)      }    },    // 删除缓存    DELETE_KEEPALIVEINCLUDES:(state, data) => {      state.keepAliveIncludes = state.keepAliveIncludes.filter(i=>i.always)    }  },
// 业务页面,应用keepAlive的组件<template>  <keep-alive :include="keepAliveIncludes" >    <router-view ref="content"/>  </keep-alive></template><script>export default {  computed: {    'keepAliveIncludes'() {      const arr = this.$store.state.keepAliveIncludes.map(i=>i.componentName)      return Array.from(new Set(arr))    },  }</script>

这样就将keepAliveIncludes跟keepalive组件绑定了
因为keepAlive组件外部对include做了订阅,所以咱们不必思考怎么删除已有缓存,只须要对keepAliveIncludes这个值解决,组件外部会帮咱们删除

通过全局路由钩子解决keepAliveIncludes

// 路由钩子router.beforeEach((to, from, next) => {    // 将所有缓存页面的keepalive拿进去扁平化    let cachePath = store.state.keepAliveIncludes.map(i => i.keepAlive).flat(Infinity)    // 去了不缓存的页面就清理所有十分驻缓存组件    if (!cachePath.includes(to.name)) {        // console.log('去了不缓存的页面');        store.commit('DELETE_KEEPALIVEINCLUDES')    }    if (to.meta.keepAlive) {        // const componentsName = to.matched[to.matched.length-1].components.default.name        store.commit('SET_KEEPALIVEINCLUDES', {            path: `${to.name}`,            componentName: to.name, //要求路由name跟默认组件的name保持一致            always: to.meta.keepAlive.length === 0,            keepAlive: to.meta.keepAlive,        })    }})

过程

先开始的执行执行思路如下:

线判断是否匹配,匹配就缓存组件
然而发现,keepAlive缓存的办法先于router.beforeEach执行,失败

起初换了思路

先缓存组件,而后在看是否匹配,不匹配就删除已有缓存

附录

此性能还是有缺点的
该办法须要默认路由组件name跟路由列表的name保持一致
因为keepAlive的include指令接管的值是组件name,而咱们应用的是异步载入组件,所以在router.beforeEach时,组件还没有实例化,没方法拿到组件的name
当然如果是同步加载组件能够用下列代码拿到组件的name

to.matched[to.matched.length-1].components.default.name

如果有大佬晓得如何解决欢送留言探讨