花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight

一、经典图解读

先放上一张经典图

花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight_第1张图片

看不懂,没关系!接下来耐心看完必然有不一样的收获。

我们常遇到的是实际是这么几个属性:

  • offsetTop
  • clientHeight
  • scrollTop
  • scrollHeight

如果不把它们弄清楚就会导致每次遇到时都混淆不清,下面就逐一看看这么些属性。

(1)offsetTop

HTMLElement.offsetTop只读属性,它返回当前元素相对于其 offsetParent 元素的顶部内边距的距离。--MDN

【巧记】offset本身就是偏移的意思,所以但凡遇到 offsetXxx 属性时需要先考虑的是参考对象。而offsetTop会经常性的被误认为其参考对象就是父元素,并不是的!!!

HTMLElement.offsetParent 是一个只读属性,返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table,td,th,body元素。当元素的 style.display 设置为 "none" 时,offsetParent 返回 nulloffsetParent 很有用,因为 offsetTop 和 offsetLeft 都是相对于其内边距边界的。--MDN

关于offsetParent的理解,这位作者给出的解读,我个人比较赞同的。

(参考的对象是)祖先(不一定是父元素,一直往上找)元素、离自己最近、position不为static(static是position的默认值,如果一个元素不设置position,默认是static定位,因此offsetTop所参考的对象的position必须是relative,absolute,fixed中的一个)--原文链接

So实在记不住,就在每次使用offsetTop的时候看看element.offsetParent,那就可以知道这个offsetTop的参考对象究竟是谁。只有明确参考对象是谁,业务中使用offsetTop,才不会用错。                                                                                                                      同理,offsetLeft、offsetRight、offsetBottom也是如此。

另外两个offset属性:offsetHeight和offsetWidth。

HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数。                                                                                                                                                                                                   通常,元素的offsetHeight是一种元素CSS高度的衡量标准,包括元素的边框、内边距和元素的水平滚动条(如果存在且渲染的话),不包含:before或:after等伪类元素的高度。 --MDN 

 这里需要知道的就是offsetHeight和clientHeight的小区别,先留下个疑问一?

(2)clientHeight

这个属性是只读属性,对于没有定义CSS或者内联布局盒子的元素为0,否则,它是元素内部的高度(单位像素),包含内边距,但不包括水平滚动条、边框和外边距。--MDN

花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight_第2张图片

MDN文档的配图就很直接的解释了clientHeight和clientWidth.

client这类属性的记忆点就在于:client,它只与元素本身相关,不关注元素外的东西。

结合上面我们说的疑问一,作个解答。                                                                                                                                                      但凡遇到 offsetXxx 属性时需要先考虑的是参考对象。                                                                                                                            这里的offsetHeight参考的就是client。而client是只与元素本身相关,所以clientHeight就不包括水平滚动条、边框和外边距。相比较,offsetHeight则会把它们都包括了,除去外边距margin

HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数。                                                                                                                                                                                                   通常,元素的offsetHeight是一种元素CSS高度的衡量标准,包括元素的边框、内边距和元素的水平滚动条(如果存在且渲染的话),不包含:before或:after等伪类元素的高度。--MDN

花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight_第3张图片

紧接着我们继续理解下clientTop这种属性,MDN的定义是一个元素顶部边框的宽度(以像素表示)。不包括顶部外边距或内边距。clientTop 是只读的。

心生疑问二:那不就是盒子的border大小?clientTop===border?

答:可以这么理解的,但和border之间会存在小差异。详细解答

https://blog.csdn.net/GuoXiaoHong7758521/article/details/90317759

总结差异点就是:clientTop是个整数值,不带单位。

同理:clientLeft、clientRight、clientBottom

 (3)scrollTop和scrollHeight

看了前面两个就知道我这里想说什么了,scroll那必然就是和滚动条有关系的了。

scrollTop

Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。这个属性可读可写,简要理解就是滚动条滚动的距离 --MDN

 所以,我们是可以通过scrollTop来控制滚动条的滚动的

scrollHeight

Element.scrollHeight 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。--MDN

花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight_第4张图片

这时候就需要知道scrollHeight和clientHeight的区别了。自个回顾下clientHeight的定义。

scrollHeight代表包括当前不可见部分的元素的高度,可以理解为是个总共高度。而可见部分的高度其实就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滚动条时讨论scrollHeight才有意义,当没有滚动条时scrollHeight==clientHeight恒成立

同理,scrollLeft和scrollWidth如此类推。

到此,我们就解读完了经典图里的大部分标注了,剩下的style类属性,就是css里设置的样式了,不作解读。

二、两个角度:子div和父div、window和html

读完上述属性,我们需要从两个角度来看看这些属性的应用方向。

1.子div和父div

前置条件:子div的高度大于父div,即子div会溢出,且溢出会滚动,那么父div就相当于可视区域了。

这时候,讨论的是这么几个值scrollHeight、clientHeight、scrollTop

就会存在这么几个情况

花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight_第5张图片

 

(1)scrollTop=0,没有滚动

(2)scrollTop>0,有滚动距离,但没有滚动到底部

(3)scrollTop=scrollHeight-clientHeight,滚动到了底部

所以在判断是否已经滚动到底部的时候就可以,用第三种情况来判断。

疑问三:为什么这里用clientHeight不用offsetHeight?

答:根据两者的定义,感觉应该都可以。因为两者相差不大,就是相差了个border的大小和水平滚动条的高度(一般情况下,垂直滚动时就不会设置水平滚动),那如果子div没有border,实际上两个值是一样的。视实际情况斟酌。

2.window和html

常见功能:页面滚动到某个位置

window.scrollTo()方法可以帮我们实现这个功能。问题就在于:某个位置这个值怎么获取?

下面就介绍两个获取html元素与浏览器窗口相关的距离变量

(1)getBoundingClientRect()

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。                                                                                返回的结果是包含完整元素的最小矩形,并且拥有left, top, right, bottom, x, y, width, 和 height这几个以像素为单位的只读属性用于描述整个边框。

这里就涉及到了可视窗口的概念了,可视窗口就是浏览器看到页面的区域,简称视口。

当我们需要获取页面中任意元素与这个视口的距离时可以用getBoundingClientRect()方法

理解:

  1. 这个方法获取到的top值是会随滚动条变化而变化的。

  2. 这个方法获取到的方位值(left、top、right、bottom)会存在负值的情况

(2)window.scrollY

定义:返回文档在垂直方向已滚动的像素值

根据业务实际情况来获取某个位置的值

三、相关的应用场景

1. 懒加载:下拉列表分页、下拉加载图片

懒加载的思路简而言之是按需加载。这个按需我们怎么来判断呢?

这里的按需指的就是:是否已经滚动到底部了?

若滚动到底部,我们就获取下一页的数据。

判断是否滚动到底部还记得是哪个公式吗?自己回滚上去再看看。

而实际情况中,不一定就是滚动到底部,可以使滚动到底部某个区间就进行获取下一页数据这个操作。

公式:scrollHeight-scrollTop-offsetHeight< y

2.  form表单报错信息定位

首个错误信息需要滚动到视口当中,结合window和html理解,就可以知道不难实现。

方法:只要将Element.getBoundingClientRect().top+window.scrollY就可以获取到报错元素在文档的位置了,你说是不是呢?

而且是不管任何时候,这个获取方法都成立。对于元素和视口的关系只有两种情况。

情况一:

元素在可视区域内,这时获取到的Element.getBoundingClientRect().top值为正值,加上window.scrollY恰恰就是元素到文档顶部的距离

情况二:

元素不在可视区域内,这时获取到的Element.getBoundingClientRect().top值为负值,加上window.scrollY,其实就是

scrollY-|Element.getBoundingClientRect().top|

也是元素到文档顶部的距离

所以

window.scrollTo(0,Element.getBoundingClientRect()+window.scrollY)就可以实现将报错元素滚动到视口顶部了

那如果不希望在贴顶部的位置展示,可以再减去一个固定值。

你可能感兴趣的:(花点时间记住scrollTop、clientHeight、offsetTop、scrollHeight)