公司后台管理系统,产品经理希望做一个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
This is demo one
然后是demo-two
// demo-two.vue
DEMO-TWO
这是ID:{{id}}
但是如果遇到需要使用动态路径参数的话,就会出现问题
- demo-two中的id不会随着路径中的id的改变而改变
-
在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}
: '')。由于
- 没有在组件上使用key。
- router-view这一层,componentOptions.tag也没有值
- 所以最终获得的key就是vnode.componentOptions.Ctor.cid
由同一个组件所渲染的实例的cid都是一样的。
所以其实根据demo-two渲染出来的5个组件的cid都是一样的,那么keep-alive其实缓存的就是同一个vnode. componentInstance。所以看到只要在一个路径下输入了input的内容,其余四个都会同时改变。
那么我们在vue-route上加上key,那么就可是实现我们想要的效果。
// @/layouts/BasicLayout.vue
keep-alive缓存路由在动态路径参数中出现的问题(二)