使用自定义的keep-alive组件,将公共页面缓存多份,都有自己的生命周期

背景:将tab页面缓存,例如A页面输入123,通过tab标签跳转到B页面,再点击A标签,跳转回A页面,这时需要保留输入的123 。本来,直接使用keep-alive就行了,但是这几个路由绑定的是同一个页面。。。。。。

  • 多个路由绑定同一个页面路由配置
 { path: '/A', name: 'A', component: CommonPage },
  { path: '/B', name: 'B', component: CommonPage },
  { path: '/C', name: 'C',component: CommonPage },
  { path: '/D', name: 'D',component: CommonPage },
  • 为什么不能直接使用keep-alive(个人理解)
    因为keep-alive是默认根据.vue文件的export default { name: 'StaStationPage',name属性来进行页面缓存的,但是多个路由指向同一个页面,那对于keep-alive来说,就只有一个对象,所以只会缓存一份。

解决方案

  • 不使用.vue文件的name属性,改用路由地址path,或路由名称name,这种比较唯一性的值作为keep-alive缓存条件,以下是自定义的keep-alive组件代码myKeepAlive.vue
<script>
  function isEmpty(...str) {
    return str.some((i) => i === undefined || i === null || i === "");
  }
  function getFirstComponentChild(children) {
    if (Array.isArray(children)) {
      return children.find(
        (c) =>
          !isEmpty(c) &&
          (!isEmpty(c.componentOptions) || (c.isComment && c.asyncFactory))
      );
    }
  }
  function removeCache(cache, key) {
    const cached = cache[key];
    cached && cached.componentInstance && cached.componentInstance.$destroy();
    delete cache[key];
  }
  function getRouterViewCacheKey(route) {
    // 建议使用route配置的那些属性作为key,例如path、name等
    return route.path
  }
  export default {
    name: "my-keep-alive",
    abstract: true,
    props: {include: Array},
    created() {
      this.cache = Object.create(null);
    },
    beforeDestroy() {
      for (const key of Object.keys(this.cache)) {
        removeCache(this.cache, key);
      }
    },
    render() {
      const slot = this.$slots.default;
      const vnode = getFirstComponentChild(slot);
      let componentOptions = vnode && vnode.componentOptions;
      if (componentOptions) {
        const child =
          componentOptions.tag === "transition"
            ? componentOptions.children[0]
            : vnode;
        componentOptions = child && child.componentOptions;
        if (componentOptions) {
          const key = getRouterViewCacheKey(this.$route)
          const { cache,include } = this;

          if (include && !include.includes(key)) {
            console.log('不含有缓存返回',include,key)
            return vnode
          }

          if (cache[key]) {
            child.componentInstance = cache[key].componentInstance;
          } else {
            cache[key] = child;
          }
          child.data.keepAlive = true;
        }
      }

      return vnode || (slot && slot[0]);
    },
  };
</script>

  • 添加中转页面,使得第一次进入该路由时,触发created,重新进入生命周期,实现第一次加载,第二次缓存的效果
    路由配置如下
{
    path: "/redirect",
    name: "Redirect",
    component: Redirect,
    children: [
      {
        path: '*',
        component: Redirect,
        meta: {
          cantCheck: true
        }
      }
    ]
  },

Redirect.vue页面代码如下:

<script>
  function replaceAll(str, substr, replacement) {
    if (str == null) return str
    return str.replace(new RegExp(substr, 'gm'), replacement)
  }
  export default {
    mounted() {
      console.info('this.$route', this.$route)
      const {fullPath} = this.$route
      this.$router.replace(`${replaceAll(fullPath, '/redirect', '')}`)
    },
    render: h => h()
  }
</script>

路由守卫permission.js,在路由跳转前,跳转到中转页面,再由中转页面跳到目标页面

	// 通过title,判断是否使用通过一个页面,并决定是否跳转到中转页
  if (to.meta.title !== undefined && to.meta.title === from.meta.title) {
    next(`/redirect${to.fullPath}`);
  } else {
    next();
  }

原有路由配置新增meta参数,修改为如下配置

  { path: '/A', name: 'A', meta: {title: 'onePage'}, component: CommonPage },
  { path: '/B', name: 'B', meta: {title: 'onePage'}, component: CommonPage },
  { path: '/C', name: 'C', meta: {title: 'onePage'}, component: CommonPage },
  { path: '/D', name: 'D', meta: {title: 'onePage'}, component: CommonPage },

至此,学习笔记记录

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值