在此之前,首先了解下 onscroll
事件和 scrollTop
属性的使用:
onscroll 元素滚动事件
描述:当元素的滚动条滚动时触发的时间。
[DOM|window|document].onscroll = function (e) {
...
}
onscroll 事件的定义与触发条件
onscroll
事件可以被任何元素绑定,包括 DOM 元素
、window 元素
、document 元素
。
默认初始情况下,只有 window
对象拥有 onscroll
事件的定义与触发条件。这是因为 window
对象包含的页面默认是当页面高度过大时自动出现滚动条,即 window
对象自带 overflow: scroll
属性,同时它也具备固定的 height
高度,所以可以触发 onscroll
事件。
也就是说,只有定义了 overflow: auto|scroll; 内容超过出现滚动条、且给定了 height 的元素本身,才能定义与触发 onscroll 事件。滚动条必须要出现,且滚动条是属于这个元素本身的。
例如:
<div id="wrap" style="height: 100px;overflow: auto;">
<div id="inner" style="height: 200px;"></div>
</div>
因为外层 wrap 元素的高度小于内层 inner 元素的高度,故当设置 overflow: auto; 时会出现滚动条,当拖拽滚动条时就会触发 wrap 的
onscroll
事件,而不是 inner 的onscroll
事件。即这个滚动条是属于 wrap 元素的,所以才会触发它的onscroll
事件。
scrollTop 距离顶部偏移值
描述:获取元素距离顶部的偏移值。
注意:scrollTop 属性必须是设置了 overflow : auto | scroll 属性的 DOM 元素才可以拥有。
同理,
scrollHeight
、scrollWidth
、scrollLeft
也是一样的。
- window 和 document 对象没有
scrollTop
属性。
例如:
<div id="wrap" style="height: 100px;overflow: auto;">
<div id="inner" style="height: 200px;"></div>
</div>
只有 wrap 元素才有
scrollTop
属性,同时可以触发onscroll
事件。
兼容性问题
获取整个 document 文档的 scrollTop:
//IE -- FF/CH var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
实现思路
业务场景:项目开发中,组件被 <keep-alive>
缓存下来后,用户点击按钮切换到其他组件页面再回来时应该还是之前浏览的位置。
- 在盒子滚动的时候,实时记录它的当前滚动高度
scrollTop
,在组件被激活时【activated】再把保存的滚动条高度赋值给要定位的元素即可。
<template>
<div>
<keep-alive> <!-- 将数据缓存下来,返回定位时不需要再次刷新请求 -->
<div ref="listCom" style="overflow-y: scroll;height: 100vh;"> <!-- 这里是关键。-->
<!-- list 滑动列表 -->
</div>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'List',
data() {
return { scrollTop: 0 }
},
mounted() {
//为可滚动,要被定为的元素,定义 onscroll 事件
this.$refs.listCom.onscroll = () => {
console.log('scroll', this.$refs.listCom.scrollTop);
this.scrollTop = this.$refs.listCom.scrollTop;
}
},
}
</script>
在移动端项目,可以给定 height: 100vh。保证有 height 属性的同时也满足了页面 height 非固定的条件,防止页面无法滑动。
- 在组件被激活时再把保存的滚动条高度赋值给要定位的元素。
<script>
export default {
name: 'List',
data() {
return { scrollTop: 0 }
},
mounted(){ .... },
activated() {
// 激活时再把之前的滚动条的高度赋值给滚动条,让它滚到对应的位置
this.$refs.artList.scrollTop = this.scrollTop;
},
}
</script>
关于计算 offsetWidth 和 offsetHeight 的问题
案例:为元素定义一个 mousemove 事件,在事件中通过获取元素的 offsetWidth 和 offsetHeight 来计算出 e.offsetX 的值位置,此时可以发现鼠标移动会有卡顿现象。
原因:这是因为每次 mousemove 鼠标移动事件触发后,浏览器都会调用内部的渲染进程去计算页面该元素的 offsetWidth 和 offsetHeight ,这相当于是直接用硬件的资源去计算,非常消耗性能,所以尽量在 mousemove 之前一次性就获取到元素的 offsetWidth 和 offsetHeight 值并处理,这样仅仅只调用一次硬件资源。