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í:
Se le puede Element.getBoundingClientRect() que use el método Element.getBoundingClientRect() para obtener el desplazamiento superior de su elemento. Este método proporciona los valores de desplazamiento total (izquierda, superior, derecha, inferior, ancho, alto) de su elemento en la ventana gráfica.
Revisa la publicación de John Resig que describe qué tan útil es este método.
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.