스크롤 속성 분석 | JD Cloud 기술팀

최근에는 슬라이딩 컴포넌트를 개발하기 위해 js를 네이티브로 사용해야 하는 프로젝트가 있고, dom 엘리먼트의 다양한 속성이 자주 사용되는데, 그 중 다양한 유형의 height와 top 속성이 대부분 비슷한 이름을 가지고 있어 그 의미가 혼동되기 쉽다. . 그래서 자주 사용하는 지식 포인트를 특별히 정리해 놓았고, 글 말미에 간단한 모바일 Scroll 컴포넌트 구현에 도전해 보겠습니다.

height와 top을 이해하기 위해서는 box model부터 시작해야 하는데 먼저 css3에 정의된 box model에 대해 알아보자. 페이지에서 DOM 요소가 차지하는 실제 영역은 다음 그림으로 설명할 수 있습니다.

 우리는 그것을 달걀이라고 생각할 수 있습니다. 외부에서 내부로

주황색 영역 - 외부 여백 여백: 달걀 껍질

검은색 영역 - 테두리 테두리: 달걀 껍질 막

녹색 영역 - 내부 여백 패딩: 알부민

흰 부분 - 내용량 : 계란 노른자

우리가 정말로 신경 쓰는 부분은 계란의 가장 영양가 있는 부분인 내용물입니다. 콘텐츠를 둘러싼 많은 레이어로 인해 페이지에서 DOM 구조의 전체 밀도를 느낄 수 있으며 조밀한 텍스트와 그림으로 인해 문제가 발생하지 않습니다. 박스 모델을 더 잘 설명하기 위해 웹 사양에 정의된 다른 인터페이스가 오늘 이야기할 주인공입니다.

 

위의 그림에서 우리는 중첩된 관계를 가진 dom 요소의 두 레이어를 설명합니다.여기의 콘텐츠 영역은 이전 그림과 다릅니다.여기의 콘텐츠 영역은 또한 독립적인 dom 요소입니다(즉, 자체 마진도 있습니다. 및 테두리. , 패딩 및 내용!, 단순화를 위해 하위 요소는 더 이상 구체적으로 그려지지 않습니다.) 하위 요소의 전체 높이가 매우 높기 때문에 상위 요소의 높이를 초과하더라도 완전히 상위 요소에 표시(그 너머 보이지 않는 부분은 회색으로 표시) 즉, 두 요소는 롤링 관계를 구성합니다. 다음 속성을 설명하려고 합니다.

一、클라이언트높이

읽기 전용 속성입니다. clientHeight는 실제로 세로 스크롤 막대의 높이입니다.일반적으로 세로 스크롤 막대는 위쪽 및 아래쪽 테두리에 가까워야 하므로 clientHeight = 위쪽 및 아래쪽 패딩 + 콘텐츠 높이입니다. 특별한 경우가 있다는 것을 잊지 마세요 가로 스크롤바가 있을 때 가로 스크롤바가 세로 스크롤바 공간의 일부를 차지하는 것도 고려해야 합니다 즉, clientHeight = up and down padding + 콘텐츠 높이 - 가로 스크롤 막대 높이입니다. 계란을 은유로 사용하는 경우 clientHeight는 껍질을 벗긴 계란입니다.

둘, 클라이언트탑

읽기 전용 속성입니다. 위쪽 테두리의 너비를 설명합니다 . 상단 테두리는 머리카락의 두께를 상기시키기 쉽습니다.다음에 거울 앞에서 자신에게 말할 수 있습니다:클라이언트탑이 줄었지만 당신도 강해졌습니다.

3. 오프셋 높이

읽기 전용 속성입니다. offsetHeight는 clientHeight와 유사합니다.관찰 결과 clientHeight보다 추가 테두리 레이어가 있음을 알 수 있습니다: offsetHeight = clientHeight + 위쪽 및 아래쪽 테두리. 이제 우리는 계란 껍질을 벗기기 전의 순간으로 돌아가 계란을 물에서 꺼내 씻어서 제시합니다-offsetHeight.

4, 오프셋상단

읽기 전용 속성입니다. offsetParent 요소의 위쪽 패딩을 기준으로 현재 요소의 거리를 반환합니다. 이 거리는 사실 자신과 부모 요소의 테두리 너비를 포함하지 않습니다. offsetTop = 자체 위쪽 여백 + 부모 요소의 위쪽 패딩, 계란과 계란 상자 사이의 배플 두께와 동일합니다.

다섯, scrollHeight

읽기 전용 속성입니다. 오버플로로 인해 보기에 표시되지 않는 콘텐츠를 포함하여 요소 콘텐츠의 높이 측정값을 설명합니다. 부모 요소에 보이지 않는 콘텐츠를 표시하도록 해킹할 수 있습니다.자식 요소는 세로 방향으로 두 부분으로 나눌 수 있습니다: 외부 여백과 내부 offsetHeight:

스크롤 관계가 있는 부모-자식 요소의 경우 scrollHeight는 다른 의미를 갖습니다.

(1) 자식 요소의 경우 자식 요소 자체에 overflow 부분이 없기 때문에 scrollHeight와 clientHeight는 같은 값을 갖는다.

(2) 부모 요소의 경우 부모 요소의 내용이 실제로 자식 요소에 의해 "지원"되므로 해당 scrollHeight는 콘텐츠 영역을 "확장"한 후의 실제 높이입니다. 부모 요소 scrollHeight = 자식 요소의 offsetHeight + 자식 요소 상하 여백 + 자체 상하 패딩

여섯, scrollTop

읽기-쓰기 속성을 사용하면 요소 콘텐츠가 세로로 스크롤되는 픽셀 수를 가져오거나 설정할 수 있습니다. 이것은 지금까지 설정을 지원할 수 있는 첫 번째 속성입니다.

(1) 초기 상태에서는 컨텐츠가 세로로 스크롤 되지 않고, 그 값은 0입니다.

(2) 콘텐츠가 세로 방향으로 아래쪽으로 스크롤될 때 콘텐츠 영역의 실제 높이는 scrollHeight이므로 표시 가능한 높이는 clientHeight이고, 이때 추가되는 부분은 scrollTop 값이 scrollHeight - clientHeight라는 것입니다 .

따라서 다음과 같이 결론을 내릴 수 있습니다. 0 <= scrollTop <= scrollHeight - clientHeight

일곱, 실전

위의 속성과 정보를 학습한 후 JD 애플릿의 스크롤 보기 구성 요소 기능을 모방하여 슬라이딩 구성 요소의 H5 버전의 공통 기능인 풀다운 새로 고침 및 목록의 풀업 로드를 구현합니다. 이 기능을 달성하기 위해 대략 세 가지 핵심 포인트로 나눌 수 있습니다.

(1) 스크롤 가능: 움직일 수 없는 셸과 슬라이딩 가능한 콘텐츠 영역이 있어야 합니다.

(2) 제스처 인식: 모바일 단말기의 터치 속성을 통해 터치엔드와 터치스타트의 손가락 위치를 비교하여 간단하게 제스처 인식을 수행할 수 있습니다.

(3) 이벤트 트리거링: 슬라이딩 위치의 임계 조건에 따라 새로 고침 및 로드 이벤트를 트리거할지 여부를 판단합니다.

구현 코드의 일부는 다음과 같습니다.

// scroller.js

export default class Scroller {
	constructor(el, option) {
		this._el = el
		this._parent = el.parentNode
		this._option = option
		this._pos = 0
		this._handleScrollStart = this.handleScrollStart.bind(this)
		this._handleScroll = this.handleScroll.bind(this)
		this.init()
	}
	init() {
		this._el.addEventListener('touchstart', this._handleScrollStart)
		this._el.addEventListener('touchend', this._handleScroll)
		if(this._option.auto) {
			this.handleRefresh()
		}
	}
	destroy() {
		this._el.removeEventListener('touchstart', this._handleScrollStart)
		this._el.removeEventListener('touchend', this._handleScroll)
	}
	handleScrollStart(e) {
		const touch = e.targetTouches[0] || e.changedTouches[0]
		this._pos = touch.clientY
	}
	handleScroll(e) {
		const touch = e.targetTouches[0] || e.changedTouches[0]
		const delta = touch.clientY - this._pos
		if(delta >= this._option.threhold) {
			// 手势向下,且下行滚动距离超过判定阈值
			if(this._parent.scrollTop == 0) {
				this.handleRefresh(e)
			}
		} else if(this._parent.scrollHeight > this._parent.clientHeight && delta <= -this._option.threhold){
			// 内容可滚动,且上行滚动距离超过判定阈值
			if(this._parent.scrollTop > this._parent.scrollHeight - this._parent.clientHeight - this._option.threhold){
				this.handleLoad(e)
			}
		}
	}
	handleRefresh(...params) {
		this._option.onRefresh && this._option.onRefresh.apply(this, params)
	}
	handleLoad(...params) {
		this._option.onRefresh && this._option.onLoad.apply(this, params)
	}
}

데모 호출:

var inner = document.getElementsById('inner')
var list = []
var pageIndex = 1
function getMockData() {
	const newData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map(i => i+(pageIndex-1)*10)
	setTimeout(() => {
	    if(pageIndex==1) { list = newData } else if(pageIndex < 5) { list.push(...newData) } else { alert('没有更多内容了') }
	    pageIndex++
	    inner.innerHTML = list.map(i => `<div class="inner-item">${i}</div>`).join('')
	}, 300)
}
function onRefresh() {
	pageIndex = 1
	getMockData()
}
new Scroller(inner, {
	threhold: 20,
	onRefresh: onRefresh,
	onLoad: getMockData,
	auto: true
})

직접 해볼 수 있고 효과도 나쁘지 않아요~~~ 토론하고 교류할 수 있는 메시지 영역에 오신 것을 환영합니다.

저자: Jingdong Retail Chen Zhen

출처: JD 클라우드 개발자 커뮤니티

 

RustDesk 1.2: Flutter를 사용하여 데스크톱 버전을 재작성하여 Wayland의 주장된 GPT-4 모델 아키텍처 유출 지원 : 혼합 전문가 모델(MoE)을 사용하여 1조 8천억 개의 매개 변수 포함 Open to all" Rust 1.71.0 안정 릴리스 React Angular.js 순간이 있습니까? Microsoft, Calibri를 대체할 새로운 기본 글꼴인 Aptos 출시Microsoft : Windows 11에서 Rust IntelliJ IDEA 2023.1.4 릴리스 를 사용하기 위한 노력 증가
{{o.이름}}
{{이름}}

추천

출처my.oschina.net/u/4090830/blog/10089164