首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在React中获取div的offsetTop位置

在React中获取div的offsetTop位置
EN

Stack Overflow用户
提问于 2015-09-19 19:47:25
回答 7查看 168.1K关注 0票数 75

我正在尝试在React中实现一个列表视图。我正在尝试实现的是存储列表头信息,并注册组件和注册scroll事件。每次用户滚动窗口时,我都想取出存储的div并重新计算offsetTop数据。

现在的问题是,我发现在onscroll函数中,控制台只打印出初始值(值是固定的,永远不会改变),offsetTop数据永远不会改变。

有人建议如何从_instances对象中获取最新的offsetTop吗?

代码语言:javascript
复制
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上,你可以从这里克隆并编译它:

Github

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2015-09-23 15:02:49

可能会鼓励您使用Element.getBoundingClientRect()方法来获取元素的顶部偏移量。此方法提供视口中元素的完整偏移值(左、上、右、下、宽、高)。

请查看描述此方法有多有用的John Resig's post

票数 92
EN

Stack Overflow用户

发布于 2019-02-18 20:07:40

我确实意识到作者提出了与基于类的组件相关的问题,但我认为值得一提的是,从React 16.8.0 (February 6, 2019)开始,您可以利用基于函数的组件中的钩子。

示例代码:

代码语言:javascript
复制
import { useRef } from 'react'

function Component() {
  const inputRef = useRef()

  return (
    <input ref={inputRef} />
    <div
      onScroll={() => {
        const { offsetTop } = inputRef.current
        ...
      }}
    >
  )
}
票数 58
EN

Stack Overflow用户

发布于 2017-07-25 02:32:21

尤金的答案使用了正确的函数来获取数据,但对于后人来说,我想确切地说明如何在React v0.14+中使用它(根据this answer):

代码语言:javascript
复制
  import ReactDOM from 'react-dom';
  //...
  componentDidMount() {
    var rect = ReactDOM.findDOMNode(this)
      .getBoundingClientRect()
  }

非常适合我,我正在使用数据滚动到刚刚挂载的新组件的顶部。

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32667847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档