keep-alive缓存路由在动态路径参数中出现的问题(一)

公司后台管理系统,产品经理希望做一个tab栏,可以切换不同的页面,类似于很早之前通过iframe的方式进行各个page之间的切换。这边直接使用的keep-alive
layout组件如下

// @/layouts/BasicLayout.vue



如下路由配置

// @/router/index.js
const routes = [{
  name: 'index',
  path: '/keep-alive',
  component: BasicLayout,
  children: [
    {
      path: 'one',
      name: 'demoOne',
      component: DemoOne
    },
    {
      path: 'two/:id',
      name: 'demoTwo',
      component: DemoTwo
    },
    {
      path: 'three/:id',
      name: 'DemoThree',
      component: DemoThree
    }
  ]
}]

然后是demo-one

// demo-one.vue

然后是demo-two

// demo-two.vue



但是如果遇到需要使用动态路径参数的话,就会出现问题

  1. demo-two中的id不会随着路径中的id的改变而改变
  2. 在demo-two/1页面中的input框输入值后,在demo-two/2,demo-two/3,demo-two/4,demo-two/5中同样会显示这个值。


    案例图片

解决方案1:使用路由组件传参

// @/router/index
// ...
    {
      path: 'two/:id',
      name: 'demoTwo',
      component: DemoTwo,
      props: true
    },
// ...
// @/pages/demo-two.vue
export default {
  props: {
    id: {
      type: String,
      required: true
    }
  },
  computed: {
    placeholder () {
      return `请输入ID:${this.id}对应的名字`
    }
  }
}

修改过后问题一得到了解决,但是问题二依然存在


修改过后问题一得到了解决,但是问题二依然存在

查看keep-alive源代码

// /Users/zhaoxuetong/github/vue/src/core/components/keep-alive.js
    const key: ?string = vnode.key == null
      // same constructor may get registered as different local components
      // so cid alone is not enough (#3269)
      ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '')
      : vnode.key

    if (cache[key]) {
      vnode.componentInstance = cache[key].componentInstance
      // make current key freshest
      remove(keys, key)
      keys.push(key)
    } else {
      cache[key] = vnode
      keys.push(key)
      // prune oldest entry
      if (this.max && keys.length > parseInt(this.max)) {
        pruneCacheEntry(cache, keys[0], keys, this._vnode)
      }
    }

keep-alive缓存子组件的使用的健名(key)的逻辑如下:
如果vnode上有key,则使用key,不过不存在key则使用componentOptions.Ctor.cid + (componentOptions.tag ? ::${componentOptions.tag} : '')。由于

  1. 没有在组件上使用key。
  2. router-view这一层,componentOptions.tag也没有值
  3. 所以最终获得的key就是vnode.componentOptions.Ctor.cid
    由同一个组件所渲染的实例的cid都是一样的。
    所以其实根据demo-two渲染出来的5个组件的cid都是一样的,那么keep-alive其实缓存的就是同一个vnode. componentInstance。所以看到只要在一个路径下输入了input的内容,其余四个都会同时改变。

那么我们在vue-route上加上key,那么就可是实现我们想要的效果。

// @/layouts/BasicLayout.vue



增加key之后的效果图.gif

打印出来的keep-alive的cache的缓存

keep-alive缓存路由在动态路径参数中出现的问题(二)

你可能感兴趣的:(keep-alive缓存路由在动态路径参数中出现的问题(一))