DOM元素尺寸:offsetWidth、clientWidth、scrollWidth

本文尺寸除了标记可写的之外 都是只读,每次访问都要重新计算。访问过多会影响性能,多次使用同一值时最好保存在局量中。

浏览器优化
由于每次回流都会造成额外的计算消耗,因此大多数浏览器都会通过队列化修改并批量执行来优化回流过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一个阈值,才清空队列。但是!当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:
offsetTop、offsetLeft、offsetWidth、offsetHeight
scrollTop、scrollLeft、scrollWidth、scrollHeight
clientTop、clientLeft、clientWidth、clientHeight
width、height
getComputedStyle()
getBoundingClientRect()
以上属性和方法都需要返回最新的布局信息,因此浏览器不得不清空队列,触发回流重绘来返回正确的值。因此,我们在修改样式的时候,最好避免使用上面列出的属性,他们都会刷新渲染队列。如果要使用它们,最好将值缓存起来。在这里插入图片描述
其中offsetTop、scrollLeft、还要补充一个clientLeft。clientLeft的值就等于border-left的值

偏移尺寸:所有视觉空间

以边框为界定来算

offsetTop 元素上边框外侧距离父元素上边框内侧的像素数
offsetLeft

当元素的父辈中没有存在position属性(除了static),含义就是该元素的margin与borde之间分界到网页文档左侧之间的距离;当某个元素的父辈中存在position属性(除了static),含义就是钙元素的的margin与borde之间分界到最近父辈元素border与padding之间分界之间的距离。

可以通过这两属性获取元素在页面中的偏移量

function getLeft(ele){
    let left=ele.offsetLeft;
    let current=ele.offsetParent;

    while(current!=null){//在DOM树中逐级上溯,一直加到根元素
        left+=current.offsetLeft;
        current=current.offsetParent;
    }
    return left;
}

offsetHeight元素垂直方向上占用的像素数,包括高度、水平滚动条的高度(注意是水平)、上下边框
offsetWidth
包括边框的长宽

客户端尺寸:内部视口大小

内容+内边距,不包含滚动条
浏览器视口大小
clientWidth
clientHeight
在不需要滚动的元素上,与滚动尺寸无差。

滚动尺寸

元素内容滚动距离的信息。有些元素例如html,无需代码自动滚动,但其他元素则需要使用CSS的overflow属性令其滚动。
scrollHeight
scrollWidth
元素内容的大小

scrollLeft
scrollTop
可写,用于确定当前元素滚动的位置,未滚动的时候都等于0

滚动回顶部

function scrollToTop(ele){
    if(ele.scrollTop!=0){
        ele.scrollTop=0;
    }
}

确定大小

可写
浏览器在每个元素上都暴露了getBoundingClientRect()方法,返回一个DOMRect对象,
包括6个属性:left、top、right、bottom相对于视口的位置,作为坐标位置,确定四个角
height、width

滚动需求

Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。
一个元素的 scrollTop 值是这个元素的内容顶部(卷起来的)到它的视口可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。
返回顶部:element.scrollTop = 0
到底部:element.scrollTop = element.scrollHeight - element.clientHeight

需求实践

列表页:宽度固定、可视高度固定、根据内容填充实际高度;支持滚动
列表下方有一个分页器:根据滚动情况动态显示当前页,支持点击翻页后滚动列表内容

首先css
留70px给底部的分页器

.scroll-container {
    height: calc(100% - 70px);
    overflow: scroll;
}

将数据划分为如下dataInPages结构,便于判断

/*
返回值dataInPages:
[
  0: [Page0Product0, Page0Product1, Page0Product2,],
  1: [Page1Product0, Page1Product1, Page1Product2,],
  ...
  lastpage
]
 */

拿到列表页的容器dom,对控制和检测其scrollTop,再加上实际列表元素的offsetTop(距离容器顶部的距离),实现需求

scrollParentRef: React.RefObject<HTMLDivElement>;
this.scrollParentRef = React.createRef<HTMLDivElement>();
<div
  className={styles.scrollContainer}
  ref={this.scrollParentRef}
  onScroll={this.onScroll}
>
列表页
</div>

维护一个state值:currentPage

onPageChange事件
currentPage变化,通过dataInPages找到目标(渲染列表元素的时候加入id属性,来索引)的offsetTop。然后设置 this.scrollParentRef.current.scrollTop

onScroll 事件
根据this.scrollParentRef.current.scrollTop和列表元素offsetTop的对比,找到列表页视口的首元素,通过dataInPages定位页码,然后修改state值:currentPage

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值