JS高级使用3.0——JS中获取页面的高度、距离顶部的距离
- 创作场景
- 阅读前提
- 提前了解的知识点
- 1. 页面可视化高度(clientHeight)
- 2. 滚动条高度(scrollHeight)
- 统计距离页面顶部的距离
- window、document、documentElement的区别
- 解读获取距离页面顶部距离的四种方式
- 如何使用代码滚动页面(四种方式)
- 1. scroll()方法
- 2. scrollBy()方法
- 3. scrollTo()
- 4. document.documentElement.scrollTop = 0(非标准写法)
- 使用节流函数优化
- 总结
创作场景
记录闭包的博客中有一个节流函数的实际用法和这个知识点相关,创作过程中发现这个知识点涉及到的还有很多,在此记录一下相关的所有知识点并进行比较。
阅读前提
此博客适用于所有人群,不仅有基础的用法,同时也对多种实现方式进行比较,本文将围绕一个例子进行讲解,并对涉及到的所有知识点进行穿插,最后进行总结。
提前了解的知识点
1. 页面可视化高度(clientHeight)
页面可视化高度指的是你当前页面能看到内容的高度
,这个高度是可以动态变化的,比如你打开了F12调试器,那么你的可视化高度就会变化,如果你将浏览器最大化,那么你的可视化高度也会变化,但这并不代表你实际页面的高度,可能你的页面高度会远远超过页面可视化高度。代码实现:
document.body.clientHeight
2. 滚动条高度(scrollHeight)
滚动条高度就是当你的页面高度超过了页面可视化高度,比如body的高度是900,你的页面高度是800,那么滚动条就会产生,一般来说,滚动条高度是比你的页面高度要大16px,可能不同设备会不一样。代码实现:
document.body.scrollHeight
统计距离页面顶部的距离
参考:https://blog.csdn.net/mouday/article/details/125444003
// 滚动方向枚举值
const DIRECTION_ENUM = {
DOWN: "down",
UP: "up",
};
// 距离顶部或底部的阈值,一般滚动条高度是要比页面高度大的,阈值指的就是大的这一点儿
const threshold = 20;
// 记录前一个滚动位置
let beforeScrollTop = 0;
function handleScroll() {
// 距顶部
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop
|| window.pageYOffset || window.scrollY;
// 可视区高度
var clientHeight =
document.documentElement.clientHeight || document.body.clientHeight;
// 滚动条总高度
var scrollHeight =
document.documentElement.scrollHeight || document.body.scrollHeight;
// 打印数值,console.table是控制台打印表格的写法,同时也有
// console.error和console.warn,对应警告和错误
// 一般使用的就是console.info
console.table([
{
label: "距顶部",
value: scrollTop,
},
{
label: "可视区高度",
value: clientHeight,
},
{
label: "滚动条总高度",
value: scrollHeight,
},
{
label: "距顶部 + 可视区高度",
value: scrollTop + clientHeight,
},
]);
// 确定滚动方向
let direction = DIRECTION_ENUM.DOWN;
if (beforeScrollTop > scrollTop) {
direction = DIRECTION_ENUM.UP;
}
// 通过滚动方向判断是触底还是触顶
if (direction == DIRECTION_ENUM.DOWN) {
// 滚动触底
if (scrollTop + clientHeight + threshold >= scrollHeight) {
console.log("滚动触底");
}
} else {
// 滚动到顶部
if (scrollTop <= threshold) {
console.log("滚动到顶部");
}
}
beforeScrollTop = scrollTop;
}
window.addEventListener('scroll', handleScroll)
window、document、documentElement的区别
window是当前页面的顶级对象,其中包含了很多属性和方法,是一个BOM对象,可进行浏览器的交互。
document是window对象的子元素,它可以理解为一个DOM对象,其中有很多方法和属性,主要是在页面元素中进行交互。
documentElement是document的子元素,注意,这是一个
只读对象
,也就是说它只能读取元素的属性,不能对元素进行操作。一般他就是你本页面的HTML元素。
这里一定要注意一下,如果你的页面是在一个iframe中
,那你获取的一定是你iframe中的所有元素,并不是你最大页面的对象。一般在实际开发中都有头部导航栏,而子页面中也会嵌套子页面,那么获取最外部的HTML元素可以用parent对象,一层一层循环,因为最外部的iframe肯定是有一个ID的,这是我在开发中遇到的一个小问题,分享一下。
// 第一个参数是当前的iframe对象,第二个是parent对象
// 调用时parentNode不用传入
function getFrameTop(frame, parentNode) {
if (frame.attr('id') !== "iframeContent") {
if (parentNode) {
frame = parentNode.parent.$("iframe")
} else {
frame = parent.$("iframe")
}
getFrameTop(frame, parent)
} else {
topIframe = frame
return frame
}
}
解读获取距离页面顶部距离的四种方式
// 距顶部
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop
|| window.pageYOffset || window.scrollY;
这四种拆分下来就是在两个对象上进行操作的,一个是window,一个是document,而之所以这么写完全是为了兼容性,尤其是pageYOffset
方法,这是一个过时方法,但是在某些IE就只能识别这个,如果你的产品不需要兼容,那其中一个就够用了。
解读一下原理:
我的div高度是900,页面可视化高度是818,而距离顶部的距离(scrollTop)是98,这其实就是滚动条的高度减去可视区高度
算出来的,而这个高度指的是你的div最顶部距离和你可视化页面的顶部距离,如果是计算底部的距离,那加上页面可视化距离即可。
如何使用代码滚动页面(四种方式)
1. scroll()方法
滚动窗口至文档中的特定位置。
window.scroll(x, y)
x和y就是你需要滚动的绝对位置坐标
window.scroll(options)options是一个对象,包含x、y坐标,同时也有滚动的方式
window.scroll({
top: 100,
left: 100,
behavior: "smooth",
});
上面这是一种标准用法,当然一般我们不这么写,直接用第一种方式滚动即可。
2. scrollBy()方法
在窗口中按指定的偏移量滚动文档(比如你只是想在这个基础上向下滚动100px)
scrollBy(x-coord, y-coord)
scrollBy(options)
x-coord 是你想滚动的水平像素值。
y-coord 是你想滚动的垂直像素值。
options
包含以下参数的字典
top
指定沿 Y 轴滚动窗口或元素的像素数。
left
指定沿 X 轴滚动窗口或元素的像素数。
behavior
指定滚动是否应该平滑(smooth)、瞬时运动到该位置(instant)、或者让浏览器选择(auto,默认)。
window.scrollBy({
top: 100,
left: 100,
behavior: "smooth",
});
这个方法和scroll区别在于,这里的x和y指的是偏移量
,而不是绝对位置
。
3. scrollTo()
这个和scroll方法是一样的,个人比较喜欢这种方式,因为可读性比较高,不容易出错,使用标准写法可以随意在x和y上进行随意滚动,因为对象上参数可选。
// 设置滚动行为改为平滑的滚动
window.scrollTo({
top: 1000,
behavior: "smooth"
});
4. document.documentElement.scrollTop = 0(非标准写法)
上面说过documentElement是一个只读属性,官方上也是这么说的,但是经过实验发现这种方式也可以用来操作页面的滚动,但不建议这么使用,也不知道会存在什么bug。
使用节流函数优化
关于节流函数是什么,这个博客中有说明
节流函数(闭包中的使用)
function throttle(func, wait){
let previous = 0;
return function() {
var now = Date.now()
var context = this
// ES5写法:var args = []; args.push.apply(null, arguments)
var args = [...arguments] // ES6数组解构知识点:复制数组
// 如果当前时间减去上一次执行时间大于我们执行函数的时间间隔再执行
if(now - previous > wait){
func.apply(context, args);
// 闭包,记录本次执行时间戳
// 这么写就是不用将上次执行的时间作为参数传给函数了
// 就算多次调用闭包不会消失,上一次执行时间不会消失,这就是闭包的常用方式
previous = now;
}
}
}
// 滚动方向枚举值
const DIRECTION_ENUM = {
DOWN: "down",
UP: "up",
};
// 距离顶部或底部的阈值,一般滚动条高度是要比页面高度大的,阈值指的就是大的这一点儿
const threshold = 20;
// 记录前一个滚动位置
let beforeScrollTop = 0;
function handleScroll() {
// 距顶部
var scrollTop =
document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset || window.scrollY;
// 可视区高度
var clientHeight =
document.documentElement.clientHeight || document.body.clientHeight;
// 滚动条总高度
var scrollHeight =
document.documentElement.scrollHeight || document.body.scrollHeight;
// 打印数值
console.table([
{
label: "距顶部",
value: scrollTop,
},
{
label: "可视区高度",
value: clientHeight,
},
{
label: "滚动条总高度",
value: scrollHeight,
},
{
label: "距顶部 + 可视区高度",
value: scrollTop + clientHeight,
},
]);
// 确定滚动方向
let direction = DIRECTION_ENUM.DOWN;
if (beforeScrollTop > scrollTop) {
direction = DIRECTION_ENUM.UP;
}
// 通过滚动方向判断是触底还是触顶
if (direction == DIRECTION_ENUM.DOWN) {
// 滚动触底
if (scrollTop + clientHeight + threshold >= scrollHeight) {
console.log("滚动触底");
}
} else {
// 滚动到顶部
if (scrollTop <= threshold) {
console.log("滚动到顶部");
}
}
beforeScrollTop = scrollTop;
}
// window.addEventListener('scroll', handleScroll)
window.addEventListener('scroll', throttle(handleScroll, 200))
这里只是一个例子,请注意,如果想要绝对精度,也就是当滚动条快速滑动的时候也要监听到,那就将延迟设置为0-50内。
总结
获取距离顶部的距离
- document.documentElement.scrollTop
- document.body.scrollTop
- window.pageYOffset
- window.scrollY
可视区高度
- document.documentElement.clientHeight
- document.body.clientHeight
滚动条总高度
- document.documentElement.scrollHeight
- document.body.scrollHeight
滚动页面
- scroll()
- scrollTo()
- scrollBy()
- document.documentElement.scrollY = 100