反应 - 向下滑动固定导航栏向上滚动,向下滑动向上滚动

时间:2017-11-22 18:01:46

标签: javascript html css reactjs jsx

tl; dr向下滚动查找适合我的解决方案!

如何在反应中固定导航栏上实现上下滑动?

使用refs或使用componentDidMount生命周期钩子的更好方法是什么?

  hideNav = (navbar) => {
    const hide = () => {
      let lastScrollTop = 0;
      const currentScrollTop = navbar.scrollTop;

      // scroll down
      if (currentScrollTop > lastScrollTop) {
      navbar.classList.add('hidden');
      } else {
      // scroll up
        navbar.classList.remove('hidden');
      }
      lastScrollTop = currentScrollTop;
    };

    window.addEventListener('scroll', hide);
  };

...在渲染方法中进一步向下:

 render() {
      return <Navbar ref={this.hideNav} />

更新

解决方案:

class Navbar extends React.Component {
  state = {
    auth: false,
    slide: 0,  // How much should the Navbar slide up or down
    lastScrollY: 0,  // Keep track of current position in state
  };

  componentWillMount() {
    // When this component mounts, begin listening for scroll changes
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    // If this component is unmounted, stop listening
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll = () => {
    const { lastScrollY } = this.state; 
    const currentScrollY = window.scrollY;


    if (currentScrollY > lastScrollY) {
      this.setState({ slide: '-48px' });
    } else {
      this.setState({ slide: '0px' });
    }
    this.setState({ lastScrollY: currentScrollY });
  };

   render() {    
    return (
      <Navbar
        style={{
          transform: `translate(0, ${this.state.slide})`,
          transition: 'transform 90ms linear',
        }}
      />
     );
   }
 }

我还没有进行任何优化,因此建议使用requestAnimationFrame,setTimeout或customEvent来限制事件。 Like here.

1 个答案:

答案 0 :(得分:1)

您不应该使用ref作为注册事件侦听器或添加/删除类的解决方案。正如您所建议的那样,您应该使用组件生命周期钩子来开始(并停止)监听窗口上的滚动。

export default class App extends Component {
  state = { hidden: false };

  constructor(props) {
    super(props);

    // Bind the function to this component, so it has access to this.state
    this.handleScroll = this.handleScroll.bind(this);
  }

  componentWillMount() {
    // When this component mounts, begin listening for scroll changes
    window.addEventListener('scroll', this.handleScroll);
  }

  componentWillUnmount() {
    // If this component is unmounted, stop listening
    window.removeEventListener('scroll', this.handleScroll);
  }

  handleScroll(e) {
    let lastScrollTop = 0;
    const currentScrollTop = navbar.scrollTop;

    // Set the state of hidden depending on scroll position
    // We only change the state if it needs to be changed
    if (!this.state.hidden && currentScrollTop > lastScrollTop) {
      this.setState({ hidden: true });
    } else if(this.state.hidden) {
      this.setState({ hidden: false });
    }
    lastScrollTop = currentScrollTop;
  }

  render() {
    // We pass a hidden prop to Navbar which can render className="hidden" if the prop is true
    return (
      <Navbar hidden={this.state.hidden} />
    );
  }
}

此外,查看您提供的滚动功能,它不会工作,因为lastScrollTop将始终为0.如果您正在寻找滚动解决方案,请查看此答案为它与您的固定导航栏需要的解决方案类似(除了隐藏而不是显示):Sticky Header after scrolling down