react offsettop javascript scroll reactjs offset

javascript - Obtener las posiciones offsetTop de div en React



offsettop javascript (4)

La respuesta de Eugene utiliza la función correcta para obtener los datos, pero para la posteridad me gustaría explicar exactamente cómo usarla en React v0.14 + (según esta respuesta ):

import ReactDOM from ''react-dom''; //... componentDidMount() { var rect = ReactDOM.findDOMNode(this) .getBoundingClientRect() }

Funciona perfectamente para mí, y estoy usando los datos para desplazarme hasta la parte superior del nuevo componente que se acaba de montar.

Estoy tratando de implementar una vista de lista en React. Lo que estoy tratando de lograr es almacenar las informaciones de los encabezados de la lista y registrar los componentes y registrar el evento de desplazamiento. Cada vez que el usuario desplaza la ventana, me gustaría sacar el div almacenado y volver a calcular los datos de offsetTop .

El problema ahora es que, encontré que la consola simplemente imprime el valor inicial (el valor es fijo y nunca se cambia) los datos de offsetTop nunca cambian en la función de onscroll .

¿Alguien ha sugerido cómo obtener el último offsetTop del objeto _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> ); } }

El código fuente completo está en Github, puedes clonarlo y compilarlo desde aquí:

Github



Una mejor solución con ref para evitar findDOMNode que se desanima.

... onScroll() { let offsetTop = this.instance.getBoundingClientRect().top; } ... render() { ... <Component ref={(el) => this.instance = el } /> ...


import ReactDOM from ''react-dom''; //... componentDidMount() { var n = ReactDOM.findDOMNode(this); console.log(n.offsetTop); }

Solo puedes tomar el offsetTop desde el Nodo.