你真的瞭解keep-alive嗎?

瞭解之前你先從動態組件說起~

component

有的時候,在不同組件之間進行動態切換是非常有用的,比如在一個多標籤的界面裏:
在這裏插入圖片描述
上述內容可以通過 Vue 的 <component> 元素加一個特殊的 is attribute 來實現:

<template>
  <div class="hello">
    <button @click="handleAbout">About</button>
    <button @click="handleHome">Home</button>
    <keep-alive>
      <component :is="currentTab"></component>
    </keep-alive>
  </div>
</template>

<script>
import About from "./about";
import Home from "./home";
export default {
  name: "HelloWorld",
  components: {
    About,
    Home
  },
  props: {
    msg: String
  },
  data() {
    return {
      currentTab: 'About'
    };
  },
  methods: {
    handleAbout () {
      this.currentTab = 'About'
    },
    handleHome () {
      this.currentTab = 'Home'
    }
  }
};
</script>

component默認每次都會銷燬和重建,那麼爲了性能優化,我們可以使用keep-alive緩存,緩存還有一些其他的作用,比如切換時保留滾動位置,切換時保留頁面輸入的內容,等等等

keep-alive

將keep-alive包裹你的component

<keep-alive>
  <component :is="currentTab"></component>
</keep-alive>

這樣就可以保留tab之間用戶的輸入的信息了,但是並不能保留滾動的位置,不信你看下面代碼,一個tab裏面不需要滾動,而另外一個tab需要滾動。

about.vue

<template>
  <div>
    about
  </div>
</template>

<script>
export default {
  
}
</script>

<style lang="">
  
</style>

home.vue

<template>
  <div class="wrapper">
    <ul>
      <li v-for="(item, index) in 50" :key="index">
        {{item}}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  
}
</script>

<style>
  .wrapper {
    height: 200px;
    overflow: auto;
  }
</style>

寫法上沒啥問題,但就是每次切換的時候不能保留滾動位置,怎麼辦???

記錄滾動位置

解決辦法

不使用component和keep-alive組件,使用v-show代替

<home v-show="currentTab==='Home'"></home>
<about v-show="currentTab==='About'"></about>

這裏有個需要注意的地方就是,需要把滾動設置到組件裏面去,而不是他們共同的父元素,因爲他們不能共用滾動,共用滾動的話滾動位置又亂了,所以不要爲了偷懶而設置在在父元素中,比如下面代碼:

<div class="container">
  <home v-show="currentTab==='Home'"></home>
  <about v-show="currentTab==='About'"></about>
</div>
    
.container {
  height: 200px;
  overflow: auto;
}

其實很多人認爲keep-alive能保留滾動位置,也許是你在配合vue-router的時候這樣使用過,看下面代碼

  <keep-alive>
    <router-view></router-view>
  </keep-alive>

其實keep-alive只能通過點擊瀏覽器自帶的返回按鈕才能記錄位置,如果你需要在A切換到B再切換到A,通過JS的路由跳轉是不能記錄位置的。來個圖片吧,這樣直觀一點:
在這裏插入圖片描述

通常我們有這樣的需求,商品列表跳轉的商品詳情頁,然後返回到商品列表,這個時候是要保留滾動位置的,既然Keep-alive做不到,我們可以使用其他方法。

通過在頁面中記錄滾動位置,當組件再次被激活時,重新設置一下頁面的滾動,代碼如下:

export default {
  // 1.綁定滾動事件
  mounted () {
    window.addEventListener('scroll', this.handleScroll)
  },
  
  // 3.當再次進入(前進或者後退)時,只觸發activated(注:只有在keep-alive加載時調用)
  activated () {
    if (this.scroll > 0) {
      this.$nextTick(() => {
        document.documentElement.scrollTop = this.scroll
        window.addEventListener('scroll', this.handleScroll)
      })
    }
  },
  
  // 4.deactivated 頁面退出時關閉事件 防止其他頁面出現問題
  deactivated () {
    window.removeEventListener('scroll', this.handleScroll)
  },
  
  methods: {
  	// 2.滾動時候保留位置
    handleScroll () {
      this.scroll = document.documentElement.scrollTop
    }
  }
};
</script>

有時候我們的頁面需要keep-alive保留狀態,有些時候我們的頁面不需要keep-alive保留狀態,這個時候可以使用屬性include和exclude屬性處理。

include 和 exclude 屬性允許組件有條件地緩存。二者都可以用逗號分隔字符串、正則表達式或一個數組來表示:

<keep-alive :include="['a', 'b']">
  <component :is="view"></component>
</keep-alive>

更多內容請參考官方文檔:鏈接

總結

  1. keep-alive可以保留頁面的狀態,比如表單輸入
  2. keep-alive可以保留觸發返回鍵的滾動位置
  3. keep-alive不能保留動態組件的滾動位置,需要使用v-show代替
  4. keep-alive不能保留通過路由切換頁面時候的滾動位置,需要在頁面組件中單獨處理
  5. keep-alive可以通過exclude排除不需要保留狀態的頁面
  6. 使用了keep-alive纔會觸發的生命週期是activated 和 deactivated
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章