首页 > 解决方案 > 如何正确更新 React 中的类名?

问题描述

在向下滚动时,我添加和删除了某些类。我想在向上滚动时恢复课程。如何仅使用 ReactJS 来完成?

我已经使用事件侦听器来更改类。

主要概念是导航栏的内容应该显示在中心,当我们向下滚动时,显示在一个div中的网站名称应该显示在导航栏上,而放在中间的内容应该向左移动显示网站名称的 div 应该会消失。当我们向上滚动到带有网站名称的 div 时,一切都应该恢复到向下滚动之前的状态。

import React, { Component } from 'react';
import '../Styles/Navbar.css';

export class Navbar extends Component {

  handleScrollToElement(event) {
    let linkPosition = document.querySelector('.collapse');
    let brandName = document.querySelector('.navbar-brand');
    if (window.pageYOffset > 250){
      linkPosition.classList.remove('justify-content-center');
      linkPosition.classList.add('justify-content-end');
      brandName.classList.remove('invisible');
      brandName.classList.add('visible');
    }
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScrollToElement);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScrollToElement);
  }

  render() {
    return (
      <div>
        <nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
          <a className='navbar-brand invisible' href='#'>Website Name</a>
          <button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
            <span className='navbar-toggler-icon'></span>
          </button>
          <div className='collapse navbar-collapse justify-content-center' id='navbarSupportedContent'>
            <ul className='navbar-nav'>
              <li className='nav-item active'>
                <a className='nav-link' href='#'>Home</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>Item 2</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>About Us</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>Contact</a>
              </li>
            </ul>
          </div>
        </nav>
        <div className='container-fluid hpage'>
          <div className='inner'>
            <h1 className='htext' >WEBSITE TITLE</h1>
          </div>
        </div>
      </div>
    )
  }
}

export default  Navbar;

标签: javascriptreactjsreact-bootstrap

解决方案


当你使用 React.js 时,你应该尽可能避免直接的 DOM 操作。如果你真的需要一个 DOM 的引用,你应该使用ref来代替。

我将设置classNameslinkPositionbrandName作为状态constructor并更新它们handleScrollToElement

每当state更改这些变量时,render都会调用该函数并更新视图。

由于scroll事件在短时间内触发很多,我也担心性能问题。所以我在代码中添加了shouldComponentUpdate以防止重新渲染未更改的视图。

您还可以考虑对要调用的滚动事件处理函数进行去抖动处理,以减少调用setState.

import React, { Component } from 'react';
import '../Styles/Navbar.css';

export class Navbar extends Component {
  constructor(props) {
    super(props);

    this.state = {
      linkPositionClassName: 'justify-content-center',
      brandNameClassName: 'invisible',
    };
  }

  handleScrollToElement(event) {
    if (window.pageYOffset > 250){
      this.setState({
        linkPositionClassName: 'justify-content-end',
        brandNameClassName: 'visible',
      });
    } else {
      this.setState({
        linkPositionClassName: 'justify-content-center',
        brandNameClassName: 'invisible',
      });
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const { linkPositionClassName, brandNameClassName } = this.state;

    // component needs to re-render only when at least one of the state changes
    return nextState.linkPositionClassName !== linkPositionClassName || nextState.brandNameClassName !== brandNameClassName;
  }

  componentDidMount() {
    window.addEventListener('scroll', this.handleScrollToElement);
  }

  componentWillUnmount() {
    window.removeEventListener('scroll', this.handleScrollToElement);
  }

  render() {
    return (
      <div>
        <nav className='navbar navbar-expand-sm bg-dark navbar-dark fixed-top'>
          <a className=`navbar-brand ${this.state.brandNameClassName}` href='#'>Website Name</a>
          <button className='navbar-toggler' type='button' data-toggle='collapse' data-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
            <span className='navbar-toggler-icon'></span>
          </button>
          <div className=`collapse navbar-collapse ${this.state.linkPositionClassName}` id='navbarSupportedContent'>
            <ul className='navbar-nav'>
              <li className='nav-item active'>
                <a className='nav-link' href='#'>Home</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>Item 2</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>About Us</a>
              </li>
              <li className='nav-item'>
                <a className='nav-link' href='#'>Contact</a>
              </li>
            </ul>
          </div>
        </nav>
        <div className='container-fluid hpage'>
          <div className='inner'>
            <h1 className='htext' >WEBSITE TITLE</h1>
          </div>
        </div>
      </div>
    )
  }
}

export default Navbar;

推荐阅读