引言:
最近的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, 如果我們同級不不需要做到緩存,那么可以使用一個更加簡單的東西:
