文章目录
- 1、vue2获取滚动条位置
- 2、vue3获取滚动条位置
- 3、解析
- 4、判断是否存在滚动条
1、vue2获取滚动条位置
document方式
export default { name: "demo", data() { return { scrollTopVal: 0, isScroll: 0 }; }, mounted() { this.$nextTick(() => { // 开启滚动条监听 document.addEventListener("scroll", this.scrollTop, true); let elVal = document.getElementsByClassName('el-drawer__body')[0]; this.isScroll = elVal.scrollHeight > elVal.clientHeight; }); }, beforeDestroy() { document.removeEventListener('scroll', this.scrollTop, true); }, methods: { scrollTop() { let elVal = document.getElementsByClassName('el-drawer__body')[0]; this.scrollTopVal = elVal.scrollTop; } } };
复制
window方式
export default { name: "demo", data() { return { scrollTopVal: 0, isScroll: 0 }; }, mounted() { this.$nextTick(() => { // 开启滚动条监听 window.addEventListener("scroll", this.scrollTop, true); let elVal = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset; this.isScroll = elVal.scrollHeight > elVal.clientHeight; }); }, beforeDestroy() { window.removeEventListener('scroll', this.scrollTop, true); }, methods: { scrollTop() { let elVal = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset; this.scrollTopVal = elVal.scrollTop; }, } };
复制
2、vue3获取滚动条位置
公共部分
import { nextTick, ref, onMounted, onBeforeUnmount } from "vue"; let scrollTopVal = ref<number>(0); let isScroll = ref<boolean>(false);
复制
document方式
onMounted(() => { // 监听滚动条位置 document.addEventListener("scroll", scrollTop, true); // 设置对应元素的滚动条 let elVal: any = document.getElementsByClassName('el-drawer__body')[0]; // 判断是否存在滚动条 isScroll.value = elVal.scrollHeight > elVal.clientHeight; }); // 实时滚动条高度 const scrollTop = () => { nextTick(() => { let elVal: any = document.getElementsByClassName('el-drawer__body')[0]; scrollTopVal.value = elVal.scrollTop; }); }; onBeforeUnmount(() => { // 参数必须和挂载时保持一致 document.removeEventListener('scroll', scrollTop, true); });
复制
window方式
onMounted(() => { // 监听滚动条位置 window.addEventListener('scroll', scrollTop, true); let elVal: any = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset; isScroll.value = elVal.scrollHeight > elVal.clientHeight; }); // 实时滚动条高度 const scrollTop = () => { nextTick(() => { let elVal: any = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset; scrollTopVal.value = elVal.scrollTop; }); }; onBeforeUnmount(() => { // 参数必须和挂载时保持一致 window.removeEventListener('scroll', scrollTop, true); });
复制
3、解析
1、获取指定元素的滚动条值。在
elementUi
组件中需要通过class
获取,因为id
是动态值。
2、使用window
方式时,只能检测到body
或页面窗口的滚动条。然而对于elementUi
的弹窗等组件获取到的滚动条值为0
。
3、addEventListener
第三个参数表示深度监听,在某些场景如果不设置第三个参数值为true
,可能监听不到对应的事件。
4、addEventListener
第二个参数需要一个函数值,可以直接以函数的形式写在里面,但是不推荐这样写。
5、addEventListener
第一个参数便是对应的事件名称,有滚动事件和鼠标事件等其他事件。
6、必须销毁scroll
事件,因为是vue
是单页面应用,如果不销毁,离开该页面后事件依然会存在,影响浏览器的性能,并且在vue3
中直接报错。所以在离开此页面之前应该销毁全局监听事件,可以在组件销毁之前销毁全局监听事件。
4、判断是否存在滚动条
判断是否存在滚动条的需求,在弹窗插件中使用得较多。因为弹窗大多会添加
overflow: hidden;
属性,如果页面超过一屏的话,添加这个属性之后页面会有晃动。
为了增强用户体验,通过判断是否有滚动条而添加margin-left
属性以抵消overflow: hidden;
之后的滚动条位置。
判断竖向滚动条
console.log(el.scrollHeight > el.clientHeight);
复制
判断横向滚动条
console.log(el.scrollWidth > el.clientWidth);
复制
特殊情况
当元素指定
overflow: hidden;
时,不会出现滚动条。所以需要对元素是否应用了overflow: hidden;
进行判断。
function hasScrolled(ele, dir = "vertical") { // 判断的方向是否设置了overflow: hidden; let style = window.getComputedStyle(ele); if ( (dir == "vertical" && style.overflowY == "hidden") || (dir == "horizontal" && style.overflowX == "hidden") ) return false; // 在判断完overflow不为hidden后,再通过两个属性来判断。 if (dir == "vertical") { return ele.scrollHeight > ele.clientHeight; } else { return ele.scrollWidth > ele.clientWidth; } }
复制
但是,以上的方法不严谨,当容器产生外边距合并的时候,也是
ele.scrollWidth > ele.clientWidth
。
<div class="box"> <h1>子元素内部内容</h1> </div>
复制
let box = document.querySelector(".box"); // scrollHeight: 63 console.log("scrollHeight: " + box.scrollHeight); // clientHeight: 42 console.log("clientHeight: " + box.clientHeight); // 是否有滚动条: true console.log("是否有滚动条: ", box.scrollHeight > box.clientHeight);
复制
特殊情况较完美的处理方式
function hasScrolled(ele, dir = "vertical") { let eleScroll = dir == "vertical" ? "scrollTop" : "scrollLeft"; // 判断scroll数值是否为0,还是其他值 let result = !!ele[eleScroll]; // 如果是其他数值(非0)这表示有滚动条 // 如果是0,则尝试移动一下滚动条,判断是否能够移动 if (!result) { // 尝试移动滚动条 ele[eleScroll] = 1; // 再次确认数值 result = !!ele[eleScroll]; // 恢复原位 ele[eleScroll] = 0; } // 得出结果 return result; }
复制
计算滚动条宽度的方法
因为移动端浏览器的滚动条都是不占据页面宽度的透明样式,所以为了进一步增强用户体验,我们还需要计算滚动条的宽度,根据情况添加合理的
margin-left
值。
新建一个带有滚动条的div
元素,再计算该元素offsetWidth
和clientWidth
的差值。
复制
function getScrollbarWidth() { let scrollDiv = document.createElement("div"); scrollDiv.style.cssText = "width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;"; document.body.appendChild(scrollDiv); let scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; document.body.removeChild(scrollDiv); return scrollbarWidth; }