保存组件中滚动区域的位置
需求
一个keepalive的组件,页面中有一个滚动区域(滚动区域渲染了列表),我们需要从此页面跳到其他页面上,然后再回到这个页面时,滚动条任然在先前的位置
问题
缓存组件会变成js对象被存储,此时他的滚动条高度信息消失,js的路由守卫配置方法只能设置页面滚动条,
思路
给滚动列表的项唯一标识符,记录离滚动视口最近的哪一项与滚动视口的相对高度top,以及这一项的id属性,回到keepalive页面时,根据top和id计算滚动区域应该滚动的高度
使用方式及注意点
-
容器形式
跟betterscroll差不多
- itemsContainer 滚动视口
- itemsList 滚动内容区
- item滚动区中的元素必须有id属性且唯一
<div class="show" @scroll="getmin()" ref="itemsContainer"> <div class="show-warpper" ref="itemsList"> <div class="item" :id ="item.id" :style="`background-color:${item.color};height:${item.height}px`" v-for="(item) in items" :key="item.id"> </div> </div> </div>
-
存储高度信息的时机
视情况而定,宗旨为可能使页面变化的一切因素,本例中是滚动事件,列表数据源变化
-
设置高度信息的时机
activated生命周期钩子(重新激活组件时)
使用方式
引入
npm install hold-scroll
拿到滚动视口,滚动内容区(通过ref)
<div class="show" ref="itemsContainer">
<div class="show-warpper" ref="itemsList">
设置seesionStorage的key,调用核心方法,保存,设置滚动高度
方法编写
//获取高度
getmin(){
const itemsContainer = this.$refs.itemsContainer
const itemswrapper = this.$refs.itemsList
holdScroll.saveHInfo(itemsContainer,itemswrapper,'list')
},
//设置高度
setmin(){
const itemsContainer = this.$refs.itemsContainer
const itemswrapper = this.$refs.itemsList
holdScroll.setHInfo(itemsContainer,itemswrapper,'list')
}
保存高度
- 滚动(设置给滚动视口)
<div class="show" @scroll="getmin()" ref="itemsContainer">
- 数据更新
updated(){
this.$nextTick(()=>{
this.getmin()
})
},
设置高度
- 组件被激活
//设置高度
activated(){
this.setmin()
},
核心方法
/**
* itemsContainer 是滚动区域,固定高度,overflow:scroll
* itemswrapper 是滚动内容容器,用来包装容器内的元素
* 容器的元素是item,方法中不用写这个参数,但是在DOM结构中需要体现
*
* @params {HTMLElement} itemsContainer
* @params {HTMLElement} itemswrapper
* @params {String} key 页面信息存储到sessionStorage 的唯一标识
* id 具有唯一标识的item元素的id,将要保存到sessionStorage的名称(key)
* top 某个特殊元素顶部到滚动区域顶部的距离,将要保存到sessionStorage的名称(key)
*
*/
function saveHInfo(itemsContainer,itemswrapper,key){
const offsetTop = itemsContainer.getBoundingClientRect().top
const itemCollections = itemswrapper.children
let items = Array.from(itemCollections)
let minId
let minTop
if(itemsContainer.getBoundingClientRect().width == 0){
return ;
}
items.forEach(item=>{
//高度
const top = item.getBoundingClientRect().top-offsetTop
if(top>=0){
if(!minId){
minId = item.id
minTop = top
}else if(top<minTop){
minTop = top
minId = item.id
}
}
})
sessionStorage.setItem(key+'_id',minId)
sessionStorage.setItem(key+'top',minTop)
}
// 设置高度
function setHInfo(itemsContainer,itemswrapper,key){
const itemCollections = itemswrapper.children
const minId = sessionStorage.getItem(key+'_id')
const minTop = sessionStorage.getItem(key+'top')
if(!minId) return
let topHeight = 0
let items = Array.from(itemCollections);
items.some(item=>{
if(item.id == minId){
topHeight+=parseInt(getComputedStyle(item).marginTop)
return true
}
topHeight+=
parseInt(getComputedStyle(item).marginTop)
+
parseInt(getComputedStyle(item).marginBottom)
+
item.offsetHeight
})
itemsContainer.scrollTop = topHeight-minTop
}