反应单页滚动即可锚定,而无需路由器或导航uri

时间:2018-12-16 19:01:58

标签: reactjs

我对设置这个太简单的页面的内容结构感到好奇。有一个导航/菜单栏,带有指向指向页面下方的锚点的链接。我不需要基于React-Router的URL哈希或历史记录跟踪。 我不想在导航栏中出现DOM查询,但是我看到的问题是我当前的设置将这些组件作为同级组件,因此为这些组件创建ref意味着必须创建一个混乱的中间处理程序在两个地方之间传递它们。

主应用

const App = () => {
  return (
    <Provider store={store}>
      <div className="app">
        <Navibar />
        <Jumbo />
        <About /> // should have a ref
        <Projects />  // should have a ref
        <Contact />  // should have a ref
      </div>
    </Provider>
  );
};

导航栏详细信息

handleClick = (e) => {
  window.scrollTo({
            top:this.myRef.current.offsetTop, 
            behavior: "smooth"
        })
}

<NavLink href="#about" onClick={this.handleClick}>About</NavLink>

在主应用程序级别,我不需要使它成为带有props / state的Class,它应该只是一个功能组件。也许这就是我的逻辑存在缺陷的地方?但是,如果我使App组件接受refCallbacks并将它们传递给Navibar,那会解决吗?

1 个答案:

答案 0 :(得分:1)

<li> onClick中的功能有助于防止handleScrollTo()在加载时触发

class App extends React.Component {
  refA = React.createRef()
  refB = React.createRef()
  
  componentDidMount() {
    this.setState({ loaded: true })
  }
  
  handleScrollTo = (elRef) => {
    // Incase the ref supplied isn't ref.current
    const el = elRef.current ? elRef.current : elRef
    
    // Scroll the element into view
    el.scrollIntoView({
      behavior: 'smooth',
      block: 'start'
    })
  }
  
  render() {
    return (
      <article>
        <header>
          <h1>ScrollTo Component</h1>
        </header>

        <nav>
          <ul>
            <li onClick={() => { this.handleScrollTo(this.refA) }}>
              Programs
            </li>
            <li onClick={() => { this.handleScrollTo(this.refB) }}>
              About
            </li>
          </ul>
        </nav>

        <div className="spacer"></div>

        <div ref={this.refA}>
          <h2>Programs</h2>
          <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>

        <div className="spacer"></div>

        <div ref={this.refB}>
          <h2>About</h2>
          <p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
        </div>
      </article>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
li {
  cursor: pointer;
}

.spacer {
  margin: 100px 0 100px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>