react里的refs遇到一个问题

代码如下:
实现效果是一个锚点导航:
通过点击获取当前点击对象的data-id属性的值,再同个这个值获取另外一个节点的offsetTop属性值。

但是现在refs.xx这里的没法写变量,有没有办法能够这样动态的获取到offset值?

static defaultProps = {
     list: [
            {
                id: '#one'
               
            },
            {
                id: '#two'
               
            },
            {
                id: '#three'
            },
            {
                id: '#four'
            },
            {
                id: '#five'
            },
            {
                id: '#six'
            }
        ]
}

clickHandler(e){
      const id = e.target.getAttribute('data-id').split('#')[1];
      const target = this.refs.id.offsetTop;
      
      //后面的处理是页面滚动到目标id的位置
}


render(){
    return (
            <div className="">
                <div className="wrap clearfix">
                    {
                        this.props.list.map((item, index) => {
                            return (
                                <a key={index} className="tab" data-id={item.id} target="_blank" onClick={this.clickHandler.bind(this)}></a>
                            )
                        })
                    }
                </div>
                <div style={{height:'500px'}}  id = "one">one</div>
                <div style={{height:'500px'}} id = "two">two</div>
                <div style={{height:'500px'}} id="three">three</div>
                <div style={{height:'500px'}} id="four">four</div>
            </div>
        );
}
阅读 4.6k
3 个回答

比如吧,有 A、B、C 三个组件,

<A data-id="b" onClick={this.clickHandler.bind(this)} />

<B ref={r => this.b = r />
<C ref={r => this.c = r />

A 组件被点击,要拿到 B 组件的 offsetTop值,

clickHandler() {
      const id = e.target.getAttribute('data-id').split('#')[1];
      const target = this[id];
      const dom = findDOMNode(target);
      console.log(dom);
}

主要就是findDOMNode这个方法,获取真实DOM,但是不建议使用了,所以还是尽量想办法用state实现吧。由于不知道你的具体业务需求,所以无法给出建议。

补充部分,这个需求的确只能操作真实DOM实现。

完整代码:

import React from 'react';
import ReactDOM from 'react-dom';

class App extends React.Component {
  handleClick = (id) => {
    const dom = ReactDOM.findDOMNode(this[id]);
    alert(dom.offsetTop);
  }
  render() {
    return (
    <div style={{ margin: 24 }}>
      <a onClick={this.handleClick.bind(this, 'thire')}>thire</a>
        <h2 ref={r => this.one = r}>One</h2>
        <p>
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
        </p>
        <h2 ref={r => this.two = r}>Two</h2>
        <p>
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
        </p>
        <h2 style={{ marginTop: 800 }} ref={r => this.thire = r}>Thire</h2>
        <p>
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
          这里是一大段正文
        </p>
    </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

点击 a 标签会弹出你需要的值,然后将页面滚动到这个位置应该就可以吧。

实际上这种常见的需求别人已经写好了,比如 https://www.npmjs.com/package...

再次强调,既然是react,就不要操作Dom.
你的这个问题如下解决:

<div ref={r => this.test = r} onClick={() => {
    const offset = this.test.offsetTop;
    console.log(offset);
    }></div>

另外一种方式可以不用ref,

onClick={this.clickHandler.bind(this,item.id)}
clickHandler(e,id) {
      const target = this[id];
      const dom = findDOMNode(target);
      console.log(dom);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题