vue中前进刷新、后退缓存用户浏览数据和浏览位置的实践
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中,不会渲染到DOM树中。
它的作用是在内存中缓存组件(不让组件销毁),等到下次渲染是,还会保留在原来的状态。
当组件在
内被切换,它的 activated
和 deactivated
这两个生命周期钩子函数将会被对应执行。
使用:
<keep-alive include="mainList"> <router-view class="child-view">router-view> keep-alive>
keep-alive的属性:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
include 和 exclude 属性允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示
max - 数字。最多可以缓存多少组件实例,一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。
keep-alive的钩子函数:
activated 和 deactivate 生命周期钩子:
设置了keepAlive缓存的组件:
activated deactivate 只要页面切换加载组件就会执行一次
第一次进入:beforeRouterEnter -> created -> … ->activated-> … ->deactivated
后续进入时:beforeRouterEnter -> activated -> deactivated
如果每次进入组件,需要更新某些数据,此时需要把这些方法写在 actived 中
当离开组件时,需要终止某些方法,需要在 deactivated 操作,比如:进入页面发起ajax,在ajax的加载没有完成时退出该页面,此时就需要将 loading(我的ajax 和 loading 是分别控制的) 置为 false
结合 router 缓存部分组件
<keep-alive> <router-view v-if="$route.meta.keepAlive">router-view> keep-alive> <router-view v-if="!$route.meta.keepAlive>
route元信息:
routers: [{ path: '/', name: 'Home', meta: { keepAlive: false // 不需要缓存 } },{ path: '/page', name: 'Page', meta: { keepAlive: true // 需要缓存 } },]
route:
routers = [ { path: '/', name: 'home', component: Home, redirect: { path: '/' }, children: [{ path: '/', name: 'index', component: List, // 列表页 meta: { isUseCache: false,// 是否需要缓存 keepAlive: true // 缓存 } }, { path: '/detail1', name: 'detail1', component: Detail1, // 详情页 meta: { keepAlive: false } // 不缓存 }] } ]
在列表页的 activated beforeRouteLeave 钩子中:
activated() { // isUseCache为false,重新刷新获取数据 if(!this.$route.meta.isUseCache){ this.list = []; // 清空原有数据 this.onLoad(); // 这是我们获取数据的函数 } }, beforeRouteLeave (to, from, next) { // 如果去详情页,就缓存 列表页面数据 if (to.name == 'Detail') { from.meta.isUseCache = true; } next(); },
那么如果在详情页面的订单状态发生改变,那么返回列表页面就需要刷新了。
那么详情页面的路由可以这样:
data() { return { isDel: false // 是否进行了删除订单的操作 } }, beforeRouteLeave (to, from, next) { if (to.name == 'List') { // 根据是否删除了订单的状态,进行判断list是否需要使用缓存数据 to.meta.isUseCache = !this.isDel; } next() }, methods: { deleteOrder () { // 删除订单的操作 code ... this.isDel = true; this.$router.go(-1) } }