緩存的場景各種各樣,稍微一改代碼就大不相同证杭。
所以我寫的只是這一種場景:緩存一個頁面(只是一個頁面携丁!)魄宏,并且記錄下這個頁面的滾動位置。
必要的因素:
1.因為設(shè)置滾動是在router.js里scrollBehavior:設(shè)置的是 body滾動距離券册,所以這個頁面不能有其他可以滾動的標(biāo)簽烁焙。
2.像mint-ui的上拉加載組件是父節(jié)點必須有overflow:hidden.所以也不能使用九火。
3.最好不要有tabbar鹦倚,或者有的話在下面再加一個相等高度的div。要不然看不到最下面的東西。
用到的功能點:
1.記錄滾動距離: window.addEventListener('scroll', this.handleScroll);
2.設(shè)置body滾動距離:router.js里scrollBehavior
3.記錄緩存組件:app.vue:<keep-alive>
正式開始:
1.在app.vue文件:
<div id="app">
<!-- 緩存需要 -->
<keep-alive :max='1'>
<router-view v-if="$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"/>
</div>
官網(wǎng)有keep-alive詳細(xì)的解釋-->傳送門
我這里用到了max解釋:max - 數(shù)字封恰。最多可以緩存多少組件實例麻养。
就是我上面提到的我只緩存一個實例
而$route.meta.keepAlive在router.js里設(shè)置
2.router.js:
{
path:'/index3',
name:'index3',
meta:{keepAlive:true},
component:() => import('./views/index3.vue')
},
3.這個時候就可以緩存頁面了。接下來是保存頁面滾動距離俭驮。
緩存頁面它有自己的生命周期:
activated:組件激活時調(diào)用
deactivated:組件停用時調(diào)用回溺。
每次進(jìn)緩存頁面時都要記錄滾動距離,所以在 activated 里調(diào)用函數(shù)并且滾動距離及時保存在sessionStorage:
index3.vue :
mounted () {
window.addEventListener('scroll', this.handleScroll);
},
// 緩存組件的話,第二次是不走mounted的混萝,
activated() {
window.addEventListener('scroll', this.handleScroll);
},
methods: {
handleScroll () {
let scrollY = window.scrollY
sessionStorage.setItem('height',JSON.stringify({h:scrollY}));
// console.log(scrollY,'scrollYindex333')
},
},
4.因為這個window.scrollY是全局的遗遵,所以在這個組件銷毀時清除this.handleScroll
deactivated () {
window.removeEventListener('scroll', this.handleScroll)
}
5.記錄頁面滾動距離成功,這時候再進(jìn)這個頁面就要設(shè)置頁面的滾動距離了逸嘀,
在router.js里:
export default new Router({
routes:{
.......
},
scrollBehavior (to, from, savedPosition) {
// 從 A ----> B
// from to
// console.log(to,'to---------')
if (to.name === 'index3') {
// 拿到滾動距離3狄!崭倘!
let num = JSON.parse(sessionStorage.getItem('height'))
num = num ? num : 0
return { x: 0, y: num.h }
}
}
下面是index3的全部代碼:
<template>
<div>
index3
<p>------分割線1---------</p>
<p>------分割線2---------</p>
<p>------分割線3---------</p>
<p>------分割線4---------</p>
<p>------分割線5---------</p>
<input type="text" style="height:60px;color:red">
<p>------分割線6---------</p>
<p>------分割線7---------</p>
<p>------分割線8---------</p>
<p>------分割線9---------</p>
<p>------分割線10---------</p>
<p>------分割線11---------</p>
<p>------分割線12---------</p>
<p>------分割線13---------</p>
<p>------分割線14---------</p>
<p>------分割線15---------</p>
<p>------分割線16---------</p>
<p>------分割線1---------</p>
<p>------分割線2---------</p>
<p>------分割線3---------</p>
<p>------分割線4---------</p>
<p>------分割線5---------</p>
</div>
</template>
<script>
export default {
name: 'index3',
data() {
return {}
},
methods: {
handleScroll () {
let scrollY = window.scrollY
sessionStorage.setItem('height',JSON.stringify({h:scrollY}));
// console.log(scrollY,'scrollYindex333')
},
},
// 及時地銷毀
mounted () {
window.addEventListener('scroll', this.handleScroll);
},
destroyed () {
/* 加上keep-alive 則這個生命周期就不會走了翼岁。。司光。所以把清除放到deactivated */
},
// 緩存組件的話琅坡,第二次是不走mounted的,
activated() {
window.addEventListener('scroll', this.handleScroll);
},
deactivated () {
window.removeEventListener('scroll', this.handleScroll)
}
}
</script>
<style>
</style>
經(jīng)歷了一周的緩存組件較勁残家,以下是我的錯誤示范榆俺。
1>
其實很想動態(tài)清除緩存組件,只是現(xiàn)在還沒有找到最好的解決方案坞淮。網(wǎng)上說的用this.$destroy()這種方法是不可行的茴晋,加上之后緩存頁面不會再緩存,跟正常頁面沒有兩樣回窘。不需要再試了诺擅。
2>
網(wǎng)上說的清除緩存使用this.$vnode.
我沒有試成功,一周了啡直。烁涌。太疲憊了苍碟。。烹玉。
首先我要緩存的組件是二級路由頁面驰怎,壓根打印不到 this.vnode.parent 是null。所以只能是一級路由頁面parent才有值二打。并且我發(fā)現(xiàn)這個parent只有在從緩存組件跳到其他頁面時才會有值。有興趣的可以試試掂榔,這個還沒有弄懂继效。
import Vue from 'vue'
/* Vue.mixin({
beforeRouteLeave(to, from, next) {
// 全局觸發(fā)此事件
//下面是條件
if(to.name === 'regionalStatistics' && from.name === 'enterpriseQuery') {
if(this.$vnode.parent && this.$vnode.parent.componentInstance.cache) {
let key = this.$vnode.key == null
? this.$vnode.componentOptions.Ctor.cid + (this.$vnode.componentOptions.tag ? `::${this.$vnode.componentOptions.tag}` : '')
: this.$vnode.key; // 當(dāng)前關(guān)閉的組件名
let cache = this.$vnode.parent.componentInstance.cache // 緩存的組件
let keys = this.$vnode.parent.componentInstance.keys // 緩存的組件名
if(cache[key] != null) {
delete cache[key]
let index = keys.indexOf(key)
if(index > -1) {
keys.splice(index, 1)
}
}
}
}
next()
}
})
*/
3>
其實使用scrollBehavior 弊端是很大的,就是它設(shè)置的只能是body的滾動距離装获,還有另外一種方法:
使用@scroll 也可以監(jiān)聽元素滾動瑞信,并且記錄下來。在頁面渲染時再賦值于元素滾動距離穴豫。
@scroll可以肉眼看到滾動條滾動到指定位置凡简,肯定沒有scrollBehavior 效果好。
但是精肃。秤涩。。我最后用了@scroll司抱,我敗在了mint-ui的上拉加載組件上筐眷。。
<div class='scrollList' @scroll="scroll">
------------------------------------------------------------------------------
/* 滾動 */
scroll() {
let height = document.getElementsByClassName('scrollList')[0].scrollTop
sessionStorage.setItem('TFD_HEIGHT',JSON.stringify({h:height}));
},
------------------------------------------------------------------------------
activated() {
setTimeout(() => {
let num = JSON.parse(sessionStorage.getItem('TFD_HEIGHT'))
document.getElementsByClassName('scrollList')[0].scrollTop = num.h
},100)
},
4>
chorme有一個插件 vue Devtools习柠,其中有一個功能可以查看緩存組件匀谣,網(wǎng)上有很多安裝的文章。
最后的最后资溃,用了這么多紙只為了kepp-alive武翎,還沒有達(dá)到預(yù)期