当你在编写某些插件的时候,你对于JavaScript的基础知识的掌握情况将会极大地影响到你写的东西。下面介绍这些基础属性及实战如下:

window.pageYOffset, window.pageXOffset

获得文档在垂直方向或者水平方向的滚动距离。现如今Vue,React大行其道的今天好多兼容性都没在考虑的范围,不过这里还是要提下。这两个属性在IE<9的浏览器是不支持的。所以完整的兼容代码是:

  
1
2
3
4
5
let supportPageOffset = window.pageXOffset !== undefined
let isCSS1Compat = ((document.compatMode || "") === "CSS1Compat")
let x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
let y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
然后在高版本的浏览器中可以用window.scrollX和window.scrollY来分别代替window.pageXOffset和window.pageYOffset。但是**IE浏览器不支持**。

document.compatMode表示用户是否在怪异模式吧或者标准模式下。怪异模式下则显示BackCompat,非怪异模式则返回CSS1Compat
之前在IE的时候调试兼容性的时候面板里面就会有怪异模式,当用户没有设定那个<!DOCTYPE html>头的时候就会
在怪异模式下,返回值是BackCompat

摘自Mozilla中关于window.pageYOffset的表述

clientWidth, clientHeight


获取元素的内宽度包括内边距(padding)离但不包括垂直滚动条,边框或者外边距(margin)。这里的元素必须是非内联的元素,除非设置内联元素默认显示属性即可设置其样式display: inline-block或者其它。clientHeightclientWidth类似。

window.innerWidth,window.innerHeight,window.outerWidth, window.outerHeight

window.innerWidth指的是窗口视窗的宽度包括垂直滚动条的宽度。window.innerHeight窗口视窗的高度包括水平滚动条的高度。window.outerHeight指的是包括整个浏览器的容器的高度。window.outerHeight类似。

以上这几个属性在IE9以下都不支持

offsetWidth, offsetHeight, offsetLeft, offsetTop, offsetParent

offsetWidth元素的宽度包括元素的边框,元素水平内边距和垂直滚动条的宽度。offsetHeight与之类似,
这里获得的数值是四舍五入到整数,如果想要获取精益的数值可以用element.getBoundingClientRect()来获取。

offsetLeft是获取元素相对于最近的定位的元素的左边距离,offsetTop类似。

但是这里有个问题当是内联元素的时候这个显示会有些奇怪,因为那个内联元素是用的Element.getClientRects来获得宽度和高度从而导致这些内联元素不是个规则的有边框的盒模型。上面的示例就可以看到。

offsetParent是获取元素最近定位的父元素。

这里需要注意的是getBoundingClientRect获取top与offsetTop的区别

看下示例就明白了:

这里的getBoundingClientRect是以视图上的位置为基准的即相对于viewport的上,右,下,左的距离,而offsetTop是以最近的定位的元素,这里的定位元素,如果目标元素是fixed或者目标元素的最近的父元素是static定位的话的话两者是相等的,否则一般是不相等(排队了元素未在视图顶部的情况)。一个是相对于视图,一个是相对于最近的有定位的父元素。

clientLeft, clientTop, window.screenX, window.screenY

clientLeft一个元素左边边框的宽度包含垂直滚动条的宽度但并不包含左外边距和左内边距。clientTop类似。

window.screenX 用户的浏览器左边框和用户的屏幕左边之间的距离

window.screenY 用户的浏览器上边框和用户的屏幕顶端之间的距离

scrollTop, scrollLeft, scrollWidth, scrollHeight

scrollTop获取或者设置一个元素垂直方向滚动的距离,表示的意思是元素方框的顶部和元素的最顶部的可见内容之间的距离。当一个元素内容没有产生垂直滚动条,那么这个值为0。

需要注意的有以下三点:

  • 当一个元素不可以滚动值为0
  • 不接受负值相反会会设置回0
  • 如果设置的最大滚动距离大于元素最大可滚动距离则只会应用元素最大可滚动距离

scrollLeft类似。

event.clientX, event.clientY

event.clientX触摸事件中的触摸点相对于视图的左位移不包括滚动的位移。event.clientY类似。
这两个可以应用在下拉刷新的插件(当是touch事件的时候), 拖拽的插件(当是鼠标事件的时候)。

大部分的属性都可以在这里找到。

接下来假设要写一个那种类似scrollspy的插件需要用到的属性有:

那么这里需要应用到元素的一个属性getBoundingClientRect可以查看这里的详细介绍,大意是这个是返回元素在视图,相对于视图左上角的位移。事实上不管滚动的容器是否是body最终都可以归纳到这个属性上面。
大概意思即:当前一个元素完全离开viewport视口的时候,会给激活下一个导航。滚动的距离要大于元素在当前滚动容器的位移。不知道有没有表述清楚呃!-.-。

这里有一个小snippet用来获取元素的滚动的距离

1
2
3
4
5
6
7
8
9
10
11
12
13
function getScrollDis () {
let supportPageOffset = window.pageXOffset !== undefined
let isCSS1Compat = ((document.compatMode || "") === "CSS1Compat")
let x = supportPageOffset ? window.pageXOffset : isCSS1Compat ? document.documentElement.scrollLeft : document.body.scrollLeft;
let y = supportPageOffset ? window.pageYOffset : isCSS1Compat ? document.documentElement.scrollTop : document.body.scrollTop;
return {
top: y,
left: x
}
}

当滚动的容器是body的时候

当滚动的容器是body的时候直接获取滚动的距离,和元素本页面的位移和滚动的距离作对比。

1
2
3
4
5
let rect = elem.getBoundingClientRect()
let scrollTop = getScrollDis().top
let offset = {}
offset.top = rect.top + win.pageYOffset - docElem.clientTop

当滚动的容器不是body的时候

与上面的是类似的只是这里需要计算的是元素相对的滚动容器不一样,可以参考下jQuery的elem.postion()来取得元素的位置。

总结这里的进行判断有两种方法,可以实时进行计算滚动距离进行比较也可以采取和Bootstrap类似的方法初始化就位移区间的计算。只是这里在某些情况下你需要手动去重新计算一下位移区间。

以上的图片均来自于https://developer.mozilla.org/zh-CN/

TodoList:

  • getBoundingClientRectgetClientRects的区别