React - 向下滚动时向上滑动固定导航栏,向上滚动时向下滑动

chi*_*lla 11 html javascript css jsx reactjs

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);
  };
Run Code Online (Sandbox Code Playgroud)

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

 render() {
      return <Navbar ref={this.hideNav} />
Run Code Online (Sandbox Code Playgroud)

更新:

解决方案:

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',
        }}
      />
     );
   }
 }
Run Code Online (Sandbox Code Playgroud)

我还没有做任何优化,所以建议使用 requestAnimationFrame、setTimeout 或 customEvent 来限制事件。像这儿。

Dan*_*vey 4

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

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} />
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

另外,查看您提供的滚动功能,它不会工作,因为lastScrollTop始终为 0。如果您正在寻找滚动解决方案,请查看此答案,因为它具有与固定导航栏所需的类似解决方案(除了隐藏而不是显示):向下滚动后粘性标题