瞭解之前你先從動態組件說起~
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>
更多內容請參考官方文檔:鏈接
總結
- keep-alive可以保留頁面的狀態,比如表單輸入
- keep-alive可以保留觸發返回鍵的滾動位置
- keep-alive不能保留動態組件的滾動位置,需要使用v-show代替
- keep-alive不能保留通過路由切換頁面時候的滾動位置,需要在頁面組件中單獨處理
- keep-alive可以通過exclude排除不需要保留狀態的頁面
- 使用了keep-alive纔會觸發的生命週期是activated 和 deactivated