利用Vue中keep-alive,快速實(shí)現(xiàn)頁(yè)面緩存

keep-alive

有時(shí)候我們不希望組件被重新渲染影響使用體驗(yàn);或者處于性能考慮,避免多次重復(fù)渲染降低性能。而是希望組件可以緩存下來,維持當(dāng)前的狀態(tài)。這時(shí)候就可以用到keep-alive組件。

官網(wǎng)解釋:<keep-alive> 包裹動(dòng)態(tài)組件時(shí),會(huì)緩存不活動(dòng)的組件實(shí)例,而不是銷毀它們。和 <transition> 相似,<keep-alive> 是一個(gè)抽象組件:它自身不會(huì)渲染一個(gè) DOM 元素,也不會(huì)出現(xiàn)在父組件鏈中。 當(dāng)組件在 <keep-alive> 內(nèi)被切換,它的 activated 和 deactivated 這兩個(gè)生命周期鉤子函數(shù)將會(huì)被對(duì)應(yīng)執(zhí)行。 在 2.2.0 及其更高版本中,activated 和 deactivated 將會(huì)在 <keep-alive> 樹內(nèi)的所有嵌套組件中觸發(fā)。 主要用于保留組件狀態(tài)或避免重新渲染

應(yīng)用場(chǎng)景

如果未使用keep-alive組件,則在頁(yè)面回退時(shí)仍然會(huì)重新渲染頁(yè)面,觸發(fā)created鉤子,使用體驗(yàn)不好。 在以下場(chǎng)景中使用keep-alive組件會(huì)顯著提高用戶體驗(yàn),菜單存在多級(jí)關(guān)系,多見于列表頁(yè)+詳情頁(yè)的場(chǎng)景如:

  • 商品列表頁(yè)點(diǎn)擊商品跳轉(zhuǎn)到商品詳情,返回后仍顯示原有信息

  • 訂單列表跳轉(zhuǎn)到訂單詳情,返回,等等場(chǎng)景。

keep-alive的生命周期

  • 初次進(jìn)入時(shí):created > mounted > activated;退出后觸發(fā) deactivated

  • 再次進(jìn)入:會(huì)觸發(fā) activated;事件掛載的方法等,只執(zhí)行一次的放在 mounted 中;組件每次進(jìn)去執(zhí)行的方法放在 activated 中

項(xiàng)目實(shí)踐

1.更改App.vue

 <div id="app" class='wrapper'>
    <keep-alive>
        <!-- 需要緩存的視圖組件 --> 
        <router-view v-if="$route.meta.keepAlive"></router-view>
     </keep-alive>
      <!-- 不需要緩存的視圖組件 -->
     <router-view v-if="!$route.meta.keepAlive"></router-view>
</div>

2.在路由中設(shè)置keepAlive

{
  path: 'list',
  name: 'itemList', // 商品管理
  component (resolve) {
    require(['@/pages/item/list'], resolve)
 },
 meta: {
  keepAlive: true,
  title: '商品管理'
 }
}

3.更改 beforeEach鉤子

這一步是為了清空無用的頁(yè)面緩存。 假設(shè)現(xiàn)在A、B兩個(gè)頁(yè)面都開啟的緩存:

  • 若第一次進(jìn)入A頁(yè)面后退出,再次進(jìn)入頁(yè)面時(shí),頁(yè)面不會(huì)刷新。這和目前的業(yè)務(wù)邏輯不符。我們想要的結(jié)果是A頁(yè)面前進(jìn)后返回,頁(yè)面保持不變,而不是退出后重新進(jìn)入保持不變。
  • 在進(jìn)入過A頁(yè)面后進(jìn)入B頁(yè)面,經(jīng)過測(cè)試后發(fā)現(xiàn),B頁(yè)面竟然會(huì)顯示A頁(yè)面的緩存,盡管url已經(jīng)改變

為了解決這個(gè)問題,需要判斷頁(yè)面是在前進(jìn)還是后退。 在beforeEach鉤子添加代碼:

let toDepth = to.path.split('/').length
let fromDepth = from.path.split('/').length
if (toDepth < fromDepth) {
  // console.log('back...')
  from.meta.keepAlive = false
  to.meta.keepAlive = true
}

記錄頁(yè)面滾動(dòng)位置

keep-alive并不會(huì)記錄頁(yè)面的滾動(dòng)位置,所以我們?cè)谔D(zhuǎn)時(shí)需要記錄當(dāng)前的滾動(dòng)位置,在觸發(fā)activated鉤子時(shí)重新定位到原有位置。 具體設(shè)計(jì)思路:

  1. 在deactivated鉤子中記錄當(dāng)前滾動(dòng)位置,使用localStorage:
deactivated () {
 window.localStorage.setItem(this.key, JSON.stringify({
 listScrollTop: this.scrollTop
 }))
}
  1. 在activated鉤子中滾動(dòng):
this.cacheData = window.localStorage.getItem(this.key) ?JSON.parse(window.localStorage.getItem(this.key)) : null
$('.sidebar-item').scrollTop(this.cacheData.listScrollTop)

歡迎在下方留言討論,更多內(nèi)容可搜索關(guān)注微信公眾號(hào)“一郭鮮”,小郭與你一起成長(zhǎng)!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容