Vue 之keep-alive的使用,實現頁面緩存

什麼是keep-alive

有時候咱們不但願組件被從新渲染影響使用體驗;或者處於性能考慮,避免屢次重複渲染下降性能。而是但願組件能夠緩存下來,維持當前的狀態。這時候就須要用到keep-alive組件。 官網釋義:html

<keep-alive> 包裹動態組件時,會緩存不活動的組件實例,而不是銷燬它們。和 <transition> 類似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出如今父組件鏈中。

當組件在 <keep-alive> 內被切換,它的 activated 和 deactivated 這兩個生命週期鉤子函數將會被對應執行。

在 2.2.0 及其更高版本中,activated 和 deactivated 將會在 <keep-alive> 樹內的全部嵌套組件中觸發。

主要用於保留組件狀態或避免從新渲染。
複製代碼

應用場景

若是未使用keep-alive組件,則在頁面回退時仍然會從新渲染頁面,觸發created鉤子,使用體驗很差。 在如下場景中使用keep-alive組件會顯著提升用戶體驗:vue

  1. 商品列表頁點擊商品跳轉到商品詳情,返回後仍顯示原有信息
  2. 訂單列表跳轉到訂單詳情,返回,等等場景。

keep-alive的生命週期

  • 初次進入時:
    1. created > mounted > activated
    2. 退出後觸發 deactivated
  • 再次進入:
    1. 只會觸發 activated
  • 事件掛載的方法等,只執行一次的放在 mounted 中;組件每次進去執行的方法放在 activated

在項目中使用

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、在路由中設置keepAlive

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

3、更改 beforeEach鉤子

這一步是爲了清空無用的頁面緩存。 假設如今A、B兩個頁面都開啓的緩存:緩存

  • 若第一次進入A頁面後退出,再次進入頁面時,頁面不會刷新。這和目前的業務邏輯不符。咱們想要的結果是A頁面前進後返回,頁面保持不變,而不是退出後從新進入保持不變。
  • 在進入過A頁面後進入B頁面,通過測試後發現,B頁面居然會顯示A頁面的緩存,儘管url已經改變~

爲了解決這個問題,須要判斷頁面是在前進仍是後退。 在beforeEach鉤子添加代碼:bash

let toDepth = to.path.split('/').length
let fromDepth = from.path.split('/').length
if (toDepth < fromDepth) {
  // console.log('後退。。。')
  from.meta.keepAlive = false
  to.meta.keepAlive = true
}
複製代碼

記錄頁面滾動位置

keep-alive並不會記錄頁面的滾動位置,因此咱們在跳轉時須要記錄當前的滾動位置,在觸發activated鉤子時從新定位到原有位置。 具體設計思路:app

  1. deactivated鉤子中記錄當前滾動位置,在這裏我使用的是localStorage
deactivated () {
   window.localStorage.setItem(this.key, JSON.stringify({
    listScrollTop: this.scrollTop
  }))
 }
複製代碼
  1. activated鉤子中滾動:
this.cacheData = window.localStorage.getItem(this.key) ? JSON.parse(window.localStorage.getItem(this.key)) : null
$('.sidebar-item').scrollTop(this.cacheData.listScrollTop)
複製代碼

參考連接:async

相關文章
相關標籤/搜索