在 React 中切换类

IT技术 javascript reactjs
2021-04-07 17:58:44

我正在为一个有菜单按钮的项目使用 react。

<a ref="btn" href="#" className="btn-menu show-on-small"><i></i></a>

还有一个 Sidenav 组件,如:

<Sidenav ref="menu" />

我编写了以下代码来切换菜单:

class Header extends React.Component {

    constructor(props){
        super(props);
        this.toggleSidenav = this.toggleSidenav.bind(this);
    }

    render() {
        return (
          <div className="header">
            <i className="border hide-on-small-and-down"></i>
            <div className="container">
          <a ref="btn" href="#" className="btn-menu show-on-small"><i></i></a>
          <Menu className="menu hide-on-small-and-down"/>
          <Sidenav />
        </div>
          </div>
        )
    }

    toggleSidenav() {
        this.refs.btn.classList.toggle('btn-menu-open');
    }

    componentDidMount() {
        this.refs.btn.addEventListener('click', this.toggleSidenav);
    }

    componentWillUnmount() {
        this.refs.btn.removeEventListener('click', this.toggleSidenav);
    }
}

问题是它this.refs.sidenav不是一个 DOM 元素,我不能在他身上添加一个类。

有人可以解释我如何Sidenav像在按钮上那样在组件上切换类吗?

5个回答

如果您希望 React 正确有效地呈现您的 DOM,您必须使用组件的状态来更新组件参数,例如类名称。

更新:我更新了示例以在单击按钮时切换 Sidemenu。这不是必需的,但您可以看到它是如何工作的。正如我所展示的,您可能需要使用“this.state”与“this.props”。我习惯于使用 Redux 组件。

constructor(props){
    super(props);
}

getInitialState(){
  return {"showHideSidenav":"hidden"};
}

render() {
    return (
        <div className="header">
            <i className="border hide-on-small-and-down"></i>
            <div className="container">
                <a ref="btn" onClick={this.toggleSidenav.bind(this)} href="#" className="btn-menu show-on-small"><i></i></a>
                <Menu className="menu hide-on-small-and-down"/>
                <Sidenav className={this.props.showHideSidenav}/>
            </div>
        </div>
    )
}

toggleSidenav() {
    var css = (this.props.showHideSidenav === "hidden") ? "show" : "hidden";
    this.setState({"showHideSidenav":css});
}

现在,当您切换状态时,组件将更新并更改 sidenav 组件的类名。您可以使用 CSS 来显示/隐藏使用类名称的 sidenav。

.hidden {
   display:none;
}
.show{
   display:block;
}
在那里使用 State 可能是正确的。我不记得我的头顶。我习惯于将 Redux 与 React 结合使用,这会强制所有 UI 更新到组件 Props 而不是状态。两者都试一下,然后使用哪个有效:)
2021-05-28 17:58:44
<Sidenav className={this.props.showHideSidenav}/> 为什么不是 this.state.showHideSidenav?
2021-06-14 17:58:44
如果使用 ES6 类,则在构造函数中设置初始状态。参考:stackoverflow.com/questions/30668326/...
2021-06-14 17:58:44

refs不是 DOM 元素。为了找到一个DOM元素,你需要先使用findDOMNodementhod。

做这个

var node = ReactDOM.findDOMNode(this.refs.btn);
node.classList.toggle('btn-menu-open');

或者,您可以像这样使用(几乎是实际代码)

this.state.styleCondition = false;


<a ref="btn" href="#" className={styleCondition ? "btn-menu show-on-small" : ""}><i></i></a>

然后您可以styleCondition根据您的状态更改条件进行更改。

你确定,它不是一个 DOM 节点?(或者也许事情发生了变化......?)因为我可以很高兴地做this.refs.nav.getElementsByTagName('ul')[0].offsetHeight......
2021-05-26 17:58:44
我建议选项 2,因为它与 React 标准相对。是的,这是最佳实践
2021-05-30 17:58:44
@Bikas 谢谢我喜欢的第二个选项
2021-06-14 17:58:44
但是为什么你向我展示了一个向我的按钮添加类的示例,因为我的问题是如何在 Sidenav 组件上添加类?
2021-06-19 17:58:44
只需更改btnmenu这没什么大不了的。我只举了一个例子,两种情况下的基本编码是相同的
2021-06-20 17:58:44

react中的切换功能

首先你应该像这样创建构造函数

constructor(props) {
        super(props);
        this.state = {
            close: true,
        };
    }

然后创建一个这样的函数

yourFunction = () => {
        this.setState({
            close: !this.state.close,
        });
    };

然后像这样使用

render() {
        const {close} = this.state;
        return (

            <Fragment>

                 <div onClick={() => this.yourFunction()}></div>

                 <div className={close ? "isYourDefaultClass" : "isYourOnChangeClass"}></div>

            </Fragment>
        )
    }
}

请给出更好的解决方案

Ori Drori 的评论是正确的,你不是在做“react方式”。在 React 中,最好不要使用 DOM 更改类和事件处理程序。在 React 组件的 render() 方法中进行;在这种情况下,这将是 sideNav 和您的标题。如何在您的代码中完成此操作的粗略示例如下。

标题

class Header extends React.Component {
constructor(props){
    super(props);
}

render() {
    return (
        <div className="header">
            <i className="border hide-on-small-and-down"></i>
            <div className="container">
                <a ref="btn" href="#" className="btn-menu show-on-small"
                onClick=this.showNav><i></i></a>
                <Menu className="menu hide-on-small-and-down"/>
                <Sidenav ref="sideNav"/>
            </div>
        </div>
    )
}

showNav() {
  this.refs.sideNav.show();
}
}

西德纳夫

 class SideNav extends React.Component {
   constructor(props) {
     super(props);
     this.state = {
       open: false
     }
   }

   render() {
     if (this.state.open) {
       return ( 
         <div className = "sideNav">
            This is a sidenav 
         </div>
       )
     } else {
       return null;
     }

   }

   show() {
     this.setState({
       open: true
     })
   }
 }

您可以在这里看到,我们没有切换类,而是使用组件的状态来呈现 SideNav。这种方式或类似方式是使用 react 的全部前提。如果您正在使用引导程序,则有一个库将引导程序元素与react的做事方式集成在一起,允许您使用相同的元素但在它们上设置状态,而不是直接操作 DOM。可以在这里找到 - https://react-bootstrap.github.io/

希望这会有所帮助,并享受使用 React 的乐趣!

Aaron Francos 方式是一个很好的干净的实现,它将解决您的问题。不过就我个人而言,我认为让 React 组件来表示 UI 的每个组件是件好事。它使代码保持module化、简洁,并使您可以非常轻松地构建应用程序并减少耦合。这真的归结为个人喜好,只要您设置组件的状态而不是直接操作 DOM,您就在正确的轨道上。:)
2021-05-24 17:58:44
这是处理此问题的更“React”式的方式。这应该对 DOM 的影响最小。我的方法是一种很酷的简单方法,但不可否认,我的反应不如现在先进。现在,我将创建一个带有条件渲染的组件。不错的回复!reactjs.org/docs/conditional-rendering.html
2021-05-29 17:58:44
谢谢 Martin,现在我明白了,但是通过推送到 this.refs.btn 的 classList 很好,还是我也应该制作那个组件?
2021-06-11 17:58:44

对于 2019 年在 React 16.8 发布后阅读本文的任何人,请查看React Hooks它确实简化了组件中状态的处理。这些文档写得很好,并附有您需要的示例。