div의 오프셋 가져오기반응의 상단 위치
React에서 List 뷰를 구현하려고 합니다.제가 목표로 하는 것은 목록 헤더 정보를 저장하고 컴포넌트를 등록하고 스크롤 이벤트를 등록하는 것입니다.사용자가 창을 스크롤할 때마다 저장된 div를 꺼내서 다시 계산하고 싶습니다.offsetTop
데이터.
문제는 콘솔이 초기값만 출력한다는 것입니다(값은 고정되어 있으며 변경되지 않습니다).offsetTop
데이터는 변경되지 않습니다.onscroll
기능.
어떻게 하면 최신 정보를 얻을 수 있을까?offsetTop
에서_instances
오브젝트?
import React, { Component } from 'react';
import ListHeader from './lib/ListHeader';
import ListItems from './lib/ListItems';
const styles = {
'height': '400px',
'overflowY': 'auto',
'outline': '1px dashed red',
'width': '40%'
};
class HeaderPosInfo {
constructor(headerObj, originalPosition, originalHeight) {
this.headerObj = headerObj;
this.originalPosition = originalPosition;
this.originalHeight = originalHeight;
}
}
export default class ReactListView extends Component {
static defaultProps = {
events: ['scroll', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll', 'resize', 'touchmove', 'touchend'],
_instances:[],
_positionMap: new Set(),
_topPos:'',
_topWrapper:''
}
static propTypes = {
data: React.PropTypes.array.isRequired,
headerAttName: React.PropTypes.string.isRequired,
itemsAttName: React.PropTypes.string.isRequired,
events: React.PropTypes.array,
_instances: React.PropTypes.array,
_positionMap: React.PropTypes.object,
_topPos: React.PropTypes.string,
_topWrapper: React.PropTypes.object
};
state = {
events: this.props.events,
_instances: this.props._instances,
_positionMap: this.props._positionMap,
_topPos: this.props._topPos
}
componentDidMount() {
this.initStickyHeaders();
}
componentWillUnmount() {
}
componentDidUpdate() {
}
refsToArray(ctx, prefix){
let results = [];
for (let i=0;;i++){
let ref = ctx.refs[prefix + '-' + String(i)];
if (ref) results.push(ref);
else return results;
}
}
initHeaderPositions() {
// Retrieve all instance of headers and store position info
this.props._instances.forEach((k)=>{
this.props._positionMap.add(new HeaderPosInfo(
k,
k.refs.header.getDOMNode().offsetTop,
k.refs.header.getDOMNode().offsetHeight
));
});
let it = this.props._positionMap.values();
let first = it.next();
this.props._topPos = first.value.originalPosition;
this.props._topWrapper = first.value.headerObj;
}
initStickyHeaders () {
this.props._instances = this.refsToArray(this, 'ListHeader');
this.initHeaderPositions();
// Register events listeners with the listview div
this.props.events.forEach(type => {
if (window.addEventListener) {
React.findDOMNode(this.refs.listview).addEventListener(type, this.onScroll.bind(this), false);
} else {
React.findDOMNode(this.refs.listview).attachEvent('on' + type, this.onScroll.bind(this), false);
}
});
}
onScroll() {
// update current header positions and apply fixed positions to the top one
console.log(1);
let offsetTop = React.findDOMNode(this.props._instances[0].refs.header).offsetTop;
}
render() {
const { data, headerAttName, itemsAttName } = this.props;
let _refi = 0;
let makeRef = () => {
return 'ListHeader-' + (_refi++);
};
return (
<div ref="listview" style={styles}>
{
Object.keys(data).map(k => {
const header = data[k][headerAttName];
const items = data[k][itemsAttName];
return (
<ul key={k}>
<ListHeader ref={makeRef()} header={header} />
<ListItems items={items} />
</ul>
);
})
}
</div>
);
}
}
소스 코드 전체가 Github에 있으므로 여기서 복제 및 컴파일할 수 있습니다.
엘리먼트.getBoundingClientRect() 메서드를 사용하여 요소의 상위 오프셋을 얻는 것이 좋습니다.이 방법은 뷰포트에서 요소의 전체 간격띄우기 값(왼쪽, 위쪽, 오른쪽, 아래쪽, 너비, 높이)을 제공합니다.
이 방법이 얼마나 유용한지 설명하는 John Resig의 게시물을 확인하십시오.
Class-based component에 대해서 질문하고 있는 것은 알고 있습니다만, React 16.8.0(2019년 2월 6일)의 시점에서는 Function-based component의 Hook을 활용할 수 있다고 생각합니다.
코드 예:
import { useRef } from 'react'
function Component() {
const inputRef = useRef()
return (
<input ref={inputRef} />
<div
onScroll={() => {
const { offsetTop } = inputRef.current
...
}}
>
)
}
Eugene의 답변은 데이터를 얻기 위해 올바른 기능을 사용하지만, 후세를 위해 React v0.14+에서 데이터를 사용하는 방법에 대해 자세히 설명하겠습니다(이 답변에 따라).
import ReactDOM from 'react-dom';
//...
componentDidMount() {
var rect = ReactDOM.findDOMNode(this)
.getBoundingClientRect()
}
완벽하게 동작하고 있고, 방금 장착된 새 컴포넌트의 맨 위로 스크롤하기 위해 데이터를 사용하고 있습니다.
React 16.3 이상을 사용하는 경우 다음과 같이 생성자에서 ref를 생성한 후 함께 사용할 구성 요소에 부착하는 것이 더 빠른 방법입니다.
...
constructor(props){
...
//create a ref
this.someRefName = React.createRef();
}
onScroll(){
let offsetTop = this.someRefName.current.offsetTop;
}
render(){
...
<Component ref={this.someRefName} />
}
import ReactDOM from 'react-dom';
//...
componentDidMount() {
var n = ReactDOM.findDOMNode(this);
console.log(n.offsetTop);
}
노드에서 offsetTop을 잡기만 하면 됩니다.
권장되지 않는 findDOMNode를 피하기 위해 ref를 사용한 더 나은 솔루션.
...
onScroll() {
let offsetTop = this.instance.getBoundingClientRect().top;
}
...
render() {
...
<Component ref={(el) => this.instance = el } />
...
onScroll에는 이 div 안에 있는 모든 네이티브 및 하위 요소가 포함된 이벤트가 있으므로 다음과 같이 사용하여 대상 요소 OffsetTop을 얻을 수 있습니다.
const getoffSet = e => {
console.log(e, e.natiiveEvent.target.childNodes[0].offsetTop)
}
return (
<div onScroll={(e) => getoffSet(e)} ref={listview} style={styles}>
</div>
)
부모에 높이 속성이 설정되어 있지 않은지 확인:
- 부모 요소에 높이가 설정되어 있지 않은 경우 스틱 요소는 스크롤할 때 고정할 영역이 없습니다.이 문제가 발생하는 이유는
스틱 요소는 용기 높이
내에서 고정/고정하는 것을 의미합니다.
부모 요소가 Flexbox인지 확인
스틱 요소의 부모가 플렉스 박스인 경우 다음 두 가지 시나리오를 확인해야 합니다.
스틱 요소에는 align-self: auto set(기본값)이 있습니다.스틱 요소에는 align-self: stretch set이 있습니다.Sticky Element Has align-self: auto Set: 이 경우 align-self 값은 부모의 align-items 값으로 계산됩니다.그렇게,
부모가 align-param: normal(기본값) 또는 align-param: stretch set을 가진 경우 스틱 요소의 높이가 확장되어 사용 가능한 공간 전체를 채운다는 것을 의미합니다.이렇게 하면 스틱 요소가 부모 내에서 스크롤할 여지가 없습니다.
스틱 요소에 align-self가 있는 경우: 스트레치 세트:
이 경우 스틱 요소는 부모 높이까지 늘어나 스크롤할 영역이 없습니다.
Flexbox 내에서 스크롤 가능한 스틱 요소를 만드는 방법: align-self 속성 값을 align-self: flex-start로 설정할 수 있습니다.이렇게 하면 스틱 요소가 선두에 배치되어 확장되지 않습니다.여기에 링크 설명을 입력합니다.
언급URL : https://stackoverflow.com/questions/32667847/get-divs-offsettop-positions-in-react
'programing' 카테고리의 다른 글
POM 오류: org.springframework를 찾을 수 없습니다.기동하다 (0) | 2023.03.14 |
---|---|
WordPress 템플릿 이름을 번역하는 방법 (0) | 2023.03.14 |
도커 컨테이너 내의 워드프레스 플러그인 업데이트 (0) | 2023.03.14 |
CSS 변환 사용: React를 사용한 변환(...)JS (0) | 2023.03.14 |
gs protocol의 의미는 무엇입니까? (0) | 2023.03.14 |