今天改bug时发现一个特别好用的元素,之前只是知道这次用到了才知道其好处。前期项目页面很多,就都是路由跳转,然后传递id获取接口什么的,到后面优化时就发现有些有筛选功能的页面在筛选后再交互跳转路由后再返回到有筛选功能的页面时会清空之前的筛选这里就需要一个有缓存的功能,当时脑子一热还是想到了一些很麻烦的方法切不好后期优化,最后度娘将这个元素推给了我。在这里也分享给大家。
两种情况
在根组件中
路由中
{
path: '/first',
name: 'first',
component: () => import('../views/alive/first.vue')
},
{
path: '/second',
name: 'second',
component: () => import('../views/alive/second.vue')
},
{
path: '/third',
name: 'third',
component: () => import('../views/alive/third.vue')
}
first.vue组件
第一个组件
second.vue组件
第二个组件
third.vue组件
第三个组件
如果我点击第一页的按钮,进入second页面,点击第二页的按钮,进入第三个页面;
然后返回second,第二个组件second.vue的背景色是绿色的
再返回first,第一个组件title的文字是红色的
其中所有的组件都被缓存了,这个使用要看项目需求哦。
在根组件中
修改路由,需要缓存的路由添加meta属性,且是否缓存keepAlive键的值设置为true。默认值是false,不用缓存的可以不用写。
{
path: '/first',
name: 'first',
component: () => import('../views/alive.vue/first.vue'),
meta: {
keepAlive: true,
}
},
{
path: '/second',
name: 'second',
component: () => import('../views/alive.vue/second.vue')
},
{
path: '/third',
name: 'third',
component: () => import('../views/alive.vue/third.vue'),
meta: {
keepAlive: true,
}
}
这样和上面一样点击跳转,再返回 first=》second=》third=》second=》first
返回的时候就只有第一个页面的字体是红色的,由缓存;第二个页面的背景是白色,没缓存。这个按需缓存的挺好用的。
再keep-alive标签内设置inlude属性,属性值为需要被缓存的路由名称,这样就是设置单个路由缓存了。
直接再需要被缓存的组件外加一层keep-alive标签,这个也是特别实用的方法。
被keep-alive包裹的组件,不会销毁,而是将需要缓存的虚拟dom(一个js对象)存在this.cache缓存中,如果渲染的name符合条件,那么虚拟dom就会从缓存中取出,重新渲染
所以被缓存的组件只在初始化的时候执行created,再次切换到那个组件是不会重新created的
v-show有一点相似,只是v-show是通过display来设置显示与隐藏
keep-alive的几个属性
需求:A页面 -> B页面 -> C页面,当C页面返回到B页面时,保存B页面的数据;但A页面到B页面时,B页面需要重新加载数据。
这个方法很多,但是我觉得这个很适用。
1、路由router中设置keepAlive:
{
path: '/first',
name: 'first',
component: () => import('../views/alive.vue/first.vue'),
meta: {
keepAlive: true,
}
}
2、修改App.vue中的router-view:
3、在B页面添加钩子函数beforeRouteLeave,重点是离开页面的时候要清除缓存:
beforeRouteLeave(to, from, next) {
if (to.path == "/second") {
from.meta.keepAlive = true;
} else {
let vnode = this.$vnode
let parentVnode = vnode && vnode.parent;
if (parentVnode && parentVnode.componentInstance && parentVnode.componentInstance.cache) {
var key = vnode.key == null
? vnode.componentOptions.Ctor.cid + (vnode.componentOptions.tag ? `::${vnode.componentOptions.tag}` : '')
: vnode.key;
var cache = parentVnode.componentInstance.cache;
var keys = parentVnode.componentInstance.keys;
if (cache[key]) {
this.$destroy()
// remove key
if (keys.length) {
var index = keys.indexOf(key)
if (index > -1) {
keys.splice(index, 1)
}
}
cache[key] = null
}
}
}
next();
},
注意: /second 对应的C页面的路由,其它不用改。
如在现在的需求中还有C页面->B页面->A页面这种固定路由导航的情况,在C页面可以直接跳转到A页面或其它页面怎样处理?这里可以在C页面加上钩子函数:
data () {
return {
fromVNode: null
}
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.fromVNode = from
})
},
beforeRouteLeave(to, from, next) {
if (to.path !== '/first') {
this.fromVNode.meta.keepAlive = false
}
next()
}
注意: /first 对应的B页面的路由,其它不用改。