主要讲下啥是 keep-alive、具体到项目中怎么用的问题。
项目相关:panda-mall
就是缓存,我们还是来看看具体的使用场景。
首先简单一点,第一种比较普遍的场景,当我们从首页
–>列表页
–>商详页
–>再返回
,这时候列表页应该是需要keep-alive
的。
然后第二种,当我们从首页
–>列表页
–>商详页
–>返回到列表页(需要缓存)
–>返回到首页(需要缓存)
–>再次进入列表页(不需要缓存)
,这时候就是按需来控制页面的keep-alive
了。
下面我们来说说在vue
中如何具体实现,我会说两种方式。
(1)介绍
(2)实现
meta
对象里定义两个值:
keepAlive
:这个路由是否需要缓存deepth
:深度,也就是页面之间的前进后退的层次关系// 首页 { path: '*', name: 'Home', // 路由懒加载:https://router.vuejs.org/zh/guide/advanced/lazy-loading.html // webpackPreload:https://www.jianshu.com/p/bbdcfeee7fbc component: () => import(/* webpackPreload: true */ '@/views/home'), meta: { keepAlive: true, deepth: 1 } }, // 商品列表 { path: '/product', name: 'Product', component: () => import('@/views/product'), meta: { keepAlive: true, deepth: 2 } }, // 商品详情 { path: '/detail', name: 'Detail', component: () => import('@/views/detail'), meta: { keepAlive: true, deepth: 3 } },
<template> <div id="app"> <keep-alive :include="include"> <router-view v-if="$route.meta.keepAlive" /> </keep-alive> <router-view v-if="!$route.meta.keepAlive" /> </div> </template>
export default { data() { return { include: [] }; }, watch: { $route(to, from) { // 如果要to(进入)的页面是需要keepAlive缓存的,把name push进include数组中 if (to.meta.keepAlive) { !this.include.includes(to.name) && this.include.push(to.name); } // 如果 要 form(离开) 的页面是 keepAlive缓存的, // 再根据 deepth 来判断是前进还是后退 // 如果是后退: if (from.meta.keepAlive && to.meta.deepth < from.meta.deepth) { const index = this.include.indexOf(from.name); index !== -1 && this.include.splice(index, 1); } } } };
设置meta
、监听路由并判断
。这里有一定要注意的是:你的路由中定义的 name 和页面中定义的 name 一定要全等,并区分大小写!!!// router.js { path: '*', name: 'Home', // name要大小写要一致 component: () => import(/ '@/views/home'), meta: { keepAlive: true, deepth: 1 } } // home.vue export default { name: 'Home', // name要大小写要一致 }
(1)问题
name
一致来说,如果团队里面大家从一开始就都定义了一个规范那还好说,但是往往大家就name
保持一致这个就可能很难。(2)实现
meta.keeAlive
字段来进行判断的,但是不用定义deepth
深度了。// 首页 { path: '*', name: 'Home', component: () => import('@/views/home'), meta: { keepAlive: true } }, // 商品列表 { path: '/product', name: 'Product', component: () => import('@/views/product'), meta: { keepAlive: true } }, // 商品详情 { path: '/detail', name: 'Detail', component: () => import('@/views/detail'), meta: { keepAlive: true } },
<router-view>
添加一个key
,这个key
就像是我们使用v-for
循环所定义的一样,大家都知道,key
的作用就是一个标识对吧,作用于vue
在虚拟 dom 进行diff
算法,提高渲染效率。<template> <div id="app"> <keep-alive> <router-view v-if="$route.meta.keepAlive" :key="key" /> </keep-alive> <router-view v-if="!$route.meta.keepAlive" :key="key" /> </div> </template> <script> export default { computed: { key() { return this.$route.fullPath; } } }; </script>
keep-alive
了。onClick() { this.$router.push({ path: '/product', query: { t: +new Date() } }) }
http://localhost:8081/#/product?t=1585898137794