vue keep-alive 的用法及使用場景


有時候我們不希望組件被重新渲染影響使用體驗;或者處於性能考慮,避免多次重復渲染降低性能。而是希望組件可以緩存下來,維持當前的狀態。這時候就可以用到keep-alive組件。

官網解釋:<keep-alive> 包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們。和 <transition> 相似,<keep-alive> 是一個抽象組件:它自身不會渲染一個 DOM 元素,也不會出現在父組件鏈中。 當組件在 <keep-alive> 內被切換,它的 activated 和 deactivated 這兩個生命周期鈎子函數將會被對應執行。 在 2.2.0 及其更高版本中,activated 和 deactivated 將會在 <keep-alive> 樹內的所有嵌套組件中觸發。 主要用於保留組件狀態或避免重新渲染。

應用場景

如果未使用keep-alive組件,則在頁面回退時仍然會重新渲染頁面,觸發created鈎子,使用體驗不好。 在以下場景中使用keep-alive組件會顯著提高用戶體驗,菜單存在多級關系,多見於列表頁+詳情頁的場景如:

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

    keep-alive的生命周期

    • 初次進入時:created > mounted > activated;退出后觸發 deactivated
    • 再次進入:會觸發 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鈎子添加代碼:

      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
      }

      記錄頁面滾動位置

      keep-alive並不會記錄頁面的滾動位置,所以我們在跳轉時需要記錄當前的滾動位置,在觸發activated鈎子時重新定位到原有位置。 具體設計思路:

      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)
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM