網(wǎng)站建設(shè)公司的服務(wù)器杭州seo全網(wǎng)營銷
文章目錄
- keep-alive多級頁面緩存實(shí)現(xiàn)
- 只適用于頁面是否緩存狀態(tài)不變的情況
- 對于上面的問題提供一種解決方案
keep-alive多級頁面緩存實(shí)現(xiàn)
只適用于頁面是否緩存狀態(tài)不變的情況
網(wǎng)上有一種很普遍的教程,不使用keep-alive
的include
屬性,而是通過在路由表中添加meta: { keepAlive: true}
,通過v-if
判斷是否使用keep-alive
<keep-alive><router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
這種寫法只適用于頁面是否緩存的狀態(tài)不變的情況
現(xiàn)實(shí)中遇到的場景是,有三個(gè)頁面(總覽頁、列表頁、詳情頁),三個(gè)頁面逐級跳轉(zhuǎn)(總覽頁 -> 列表頁 -> 詳情頁)。因?yàn)榱斜眄撌欠猪搼屑虞d的,用戶希望可以從詳情頁返回時(shí)可以直接定位到之前的位置
因此要實(shí)現(xiàn)的實(shí)際上為頁面緩存+記錄滾動條位置,這里先看頁面緩存
網(wǎng)上很多教程的寫法是,在列表頁使用beforeRouteLeave
,動態(tài)設(shè)置keepAlive的值
// 列表頁
beforeRouteLeave(to, from, next) {if (to.name === "詳情頁") {from.meta.keepAlive = true; } else {from.meta.keepAlive = false;this.$destroy();}next();
},
乍一看沒什么問題,到詳情頁的時(shí)候?qū)eepAlive設(shè)為true進(jìn)行緩存,返回到總覽頁的時(shí)候設(shè)置為false取消緩存,但仔細(xì)想一下,這樣寫是晚一步的,是否緩存在剛進(jìn)入頁面時(shí)就定下來了,在beforeRouteLeave
的時(shí)候修改keepAlive,相當(dāng)于修改的是下次進(jìn)入頁面時(shí)是否緩存
實(shí)際流程會變?yōu)?/p>
理想狀態(tài)下
總覽頁 此時(shí)列表頁路由的keepAlive默認(rèn)為true 點(diǎn)擊進(jìn)入列表頁
列表頁 點(diǎn)擊進(jìn)入詳情頁 此時(shí)會緩存列表頁,keepAlive仍為true
詳情頁 返回列表頁 獲取緩存
這部分流程沒有問題,接下來
列表頁 返回總覽頁 列表頁被銷毀,keepAlive變?yōu)閒alse
總覽頁 點(diǎn)擊進(jìn)入列表頁 列表頁keepAlive為false
這次列表頁將不會被緩存,此時(shí)已經(jīng)出現(xiàn)問題
那我們是不是可以不設(shè)置from.meta.keepAlive = false;
,只在返回時(shí)銷毀keep-alive的緩存,此時(shí)又出現(xiàn)了一個(gè)新的問題,在使用this.$destroy();
銷毀組件后會導(dǎo)致緩存異常(回退時(shí)不使用緩存的列表頁,而是創(chuàng)建了個(gè)新的,并且會一直緩存)。詳情可以百度this.$destroy()導(dǎo)致keep-alive緩存異常
Reference:vue-router時(shí) keep-alive 頁面緩存問題解決 - 知乎
調(diào)用$destroy后,組件生命周期出現(xiàn)異常。 · Issue #6961 · vuejs/vue · GitHub
所以要實(shí)現(xiàn)類似功能,就使用include和exclude,很多帖子純純的坑
對于上面的問題提供一種解決方案
還是對需要緩存的路由添加meta: { keepAlive: true}
維護(hù)一個(gè)頁面棧,將訪問過的頁面添加進(jìn)去,如果當(dāng)前進(jìn)入的頁面在之前訪問過,代表是回退操作,則將頁面棧中在本頁面之后的數(shù)據(jù)刪除,使用include記得要給組件添加name
<template><div id="app"><keep-alive :include="cachePageList"><router-view></router-view></keep-alive></div>
</template>
<script>export default {data(){return {pageRouteList: [] // 訪問過的頁面棧}},computed: {cachePageList(){// 緩存只取頁面棧中router設(shè)置了keepAlive的return this.pageRouteList.filter(route => route.meta.keepAlive).map(route => route.name)}},watch: {$route(to, from) {const index = this.pageRouteList.findIndex(route => route.fullPath === to.fullPath)const isVisited = index !== -1if (!isVisited) {this.pageRouteList.push(to)} else {this.pageRouteList.splice(index + 1)}}}}
</script>