引言:
最近的vue單頁面項目要實現一個利用頁面緩存的優化, 即前進刷新頁面,后退不刷新頁面的功能, 並且並列的頁面也要實現緩存的效果.
舉例: A頁面, B頁面, C頁面
keep-alive:
想要是頁面緩存就要用到keep-alive這個標簽,
把keep-aline包裹router-view就能事項頁面緩存:
<keep-alive> <router-view class="Router" ></router-view> </keep-alive>
但是,並不是所有的頁面都要緩存, 有些需要,有些又不需要緩存, 這時候就要用到找個東西來區分他,
meta:路由原信息,
我們利用這個來區分哪些是要緩存,哪些是不要緩存的
在router.js里面給每個路由都添加
{ path: '/home', name: 'home', component: () => import ('@/views/Home.vue'), meta: { keepAlive: true, //此組件需要被緩存 }, }, { path: '/home', name: 'home', component: () => import ('@/views/Home.vue'), meta: { keepAlive: false, //此組件不需要被緩存 }, },
在app.vue里面通用meta來區分
<keep-alive> <router-view class="Router" v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view class="Router" v-if="!$route.meta.keepAlive"></router-view>
實現動態緩存:
做了上面的處理后, 就已經可以實現緩存了, 但是如果一個頁面有多個入口進入, 第一個入口進入了,第二個再進入,那么就會造成數據不會刷新的后果,
這時候我們可以給每個路由在添加一個用於刷新: isBack
{ path: '/home', name: 'home', component: () => import ('@/views/Home.vue'), meta: { keepAlive: true, //此組件需要被緩存 isBack: false }, },
使用:beforeRouteEnter, beforeRouteLeave, activated,
他們執行的順序是 :beforeRouteEnter ---- > beforeRouteLeave --------> activated,
beforeRouteEnter 和 beforeRouteLeave都是組件內部的導航鈎子, 每次離開和進入都會觸發,
activated:是只有在keep-alive有的情況下才出現的鈎子, 每次進入組件都會觸發, (create只有在第一次進入組件才會觸發)
比如從B頁面進入A頁面:
判斷是不是B頁面來的, 如果是B頁面來的就設置isBack=true, activated中就不會執行初始化的代碼, 如果不是B頁面來就是false(說明是A頁面來的),就執行初始化的代碼
這樣就實現了動態緩存了:
beforeRouteEnter(to, from, next) { if (from.name == 'B頁面') { to.meta.isBack = true; } next(); }, activated() { if (!this.$route.meta.isBack) { this.inits(); } this.$route.meta.isBack = false this.isFirstEnter = false; },
刷新后的出現的問題:
如果我現在從B到了C頁面, 這時候我刷新了頁面, 那么頁面上的所有數據都會初始化, 然后我在回到B頁面,這時,from.name == 'C頁面', to.meta.isBack= true,
這時候就不會重新加載數據了,但是問我原來的數據也初始化了,這就會出現問題.
解決辦法:添加另外一個參數 isFirstEnter = true
created() { this.isFirstEnter = true; }, beforeRouteEnter(to, from, next) { if (from.name == 'C頁面') { to.meta.isBack = true; } next(); }, activated() { if (!this.$route.meta.isBack || this.isFirstEnter) { this.inits(); } this.$route.meta.isBack = false this.isFirstEnter = false; },
內存過多導致頁面遲緩:
當點擊的頁面越多的時候,緩存就會越多,緩存 太多之越來越多之后頁面就會越來越卡,
解決辦法 - - 每次返回之后都銷毀掉組件:
使用: beforeRouteLeave 判斷將要去的是哪個頁面, 如果不是去的下個頁面(那肯定是上個頁面), 那么就直接銷毀掉本頁面
beforeRouteEnter(to, from, next) { if (from.name == 'detail') { to.meta.isBack = true; } next(); }, beforeRouteLeave(to, from, next) { if (to.name != '下個頁面') { this.$destroy() } next(); }, activated() { if (!this.$route.meta.isBack || this.isFirstEnter) { this.inits(); } this.$route.meta.isBack = false this.isFirstEnter = false; },
記錄滾動的位置:
beforeRouteLeave(to, from, next) { this.scrollTop = document.querySelector("#scrollRef").scrollTop //記錄位置 if (to.name != 'detail') { this.$destroy() } next(); }, activated() { if (!this.$route.meta.isBack || this.isFirstEnter) { this.inits(); } if (this.scrollTop) { document.querySelector("#scrollRef").scrollTop = this.scrollTop //設置位置 } this.$route.meta.isBack = false this.isFirstEnter = false; },
這樣就實現前進不刷新后退刷新的功能, 但是我這樣做需要每個頁面都去寫一遍這些步驟,這樣感覺不是特別好, 希望能有大神能有更好的辦法,
參考文章:https://www.cnblogs.com/wonyun/p/8763314.html
補充:
這種方法,是為了實現同級路由切換也做到緩存效果例如大多數的App, 如果我們同級不不需要做到緩存,那么可以使用一個更加簡單的東西: