最近在開發中遇到了這樣的一個問題:vue
A、B、C三個頁面,有以下這樣的場景:node
(1)從頁面A離開進入B或C的時候,緩存A頁面的數據,而且返回到A後,能保持A頁面的跳轉前職位數組
(2)離開B進入C的時候,緩存B緩存
(3)離開B進入A的時候,不緩存app
如今開始分步解決:異步
方案一:函數
從場景中但是看出A、B是須要緩存的,測試
首先修改app.vuethis
<template> <div id="app"> <keep-alive :include="['Index', 'List']"> <router-view/> </keep-alive> </div> </template>
include是A、B頁面中的name值,注意,include接受的是數組字符串url
而後就是A頁面進入B頁面的時候刷新,即離開B進入A的時候不緩存,那麼就須要用到beforeRouteEnter(),此函數在mounted()執行後執行,不是methods中的自定義函數
export default {
name: "List",
beforeRouteEnter(to, from, next) {
next(vm => {
// 經過 `vm` 訪問組件實例
if (from.fullPath == '/' && to.fullPath.indexOf('/list') > -1) { //必定是從A進到B頁面才刷新
vm.initFn(); //initFn是原本寫在mounted裏面的各類, 執行順序是:先執行mounted,而後是此處
}
})
},
methods: {
initFn() {
... //獲取數據
}
}
}
返回到原來的位置用到的是router中的scrollBehavior():
router.js:
new Router({
routes: [],
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回緩存頁面後記錄瀏覽位置
if (savedPosition && to.meta.isKeepAlive) {
return savedPosition;
}
// 異步滾動操做
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 1 });
}, 0);
});
}
})
有時候會有返回不回去的狀況,可作延時處理:
new Router({
routes: [],
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回緩存頁面後記錄瀏覽位置
if (savedPosition && to.meta.isKeepAlive) {
setTimeout(() => { //延時
window.scrollTo(savedPosition.x, savedPosition.y)
}, 10);
}
// 異步滾動操做
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 1 });
}, 0);
});
}
})
除了使用keep-alive的include屬性,可經過給router中添加mate參數控制
app.vue:
<template> <div id="app"> <keep-alive> <router-view v-if="$route.meta.isKeepAlive"/> </keep-alive> <router-view v-if="!$route.meta.isKeepAlive"/> </div> </template>
注意此處if判斷中的meta後的值要與router中的一致
router.js
const router = new Router({
routes: [
{
path: '/',
name: 'Index',
component: Index,
meta: {
isKeepAlive: true
}
},
{
path: '/list/:id',
name: 'List',
component: List,
meta: {
isKeepAlive: true
}
}
],
scrollBehavior(to, from, savedPosition) {
// keep-alive 返回緩存頁面後記錄瀏覽位置
if (savedPosition && to.meta.isKeepAlive) {
return savedPosition;
}
// 異步滾動操做
return new Promise((resolve) => {
setTimeout(() => {
resolve({ x: 0, y: 1 });
}, 0);
});
}
});
export default router;
固然還有其餘的解決方法,如destory()。
方案二:
利用$destroy()銷燬:
beforeRouteLeave (to: any, from: any, next: any) {
// 導航離開該組件的對應路由時調用
// 判斷是不是去往頁面 C
if (to.name !== 'C') {
// 不是去 C 頁面,不緩存
this.$destroy()
}
next()
}
但bug是銷燬後將永遠不會再次緩存。
網上還有給出其餘方案,查看源碼能夠發現緩存是經過添加cache屬性存儲vnode的,如經過源碼的cache屬性,強制移除某個對象,缺點是沒有完全銷燬依舊佔內存,不過我沒有實驗,具體的就不知道了。
還有就是動態設置router.js中的keepAlive值,經過beforeRouteLeave(to, from, next)中的to,from判斷url,動態設置keepAlive是true仍是false,但設置爲true緩存後,即便再設置爲false也不會清除緩存,那麼會出現bug,列表頁不一樣id的進入,始終是第一次進入時的數據。
通過屢次測試,發現方案一的兩種寫法均是可行且沒出現bug的,記錄下,方便之後複習