如何在react组件中的 mousedown/mouseup 上切换类?

IT技术 javascript reactjs
2021-05-24 15:38:22

我试图在react组件中切换一个类,如果用户将鼠标放在按钮上,那么它会向该按钮添加一个类,当用户使用鼠标时,它会恢复并删除该类从按钮。

按照此处的官方 ReactJS 文档中的解释和示例,我设法将以下代码段放在一起,但它不起作用并且不断在控制台上抛出语法错误:

import React from 'react';

export class Buttons extends React.Component{

    toggleClass() {
        if this.classList.has('btnDown') {
            this.classList.remove('btnDown');
        } else {
            this.classList.add('btnDown');
        }
    }


    render(){
        return (
            <div className="btn-wrap">
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '1' >1</button>
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '2' >2</button>
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '3' >3</button>
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '4' >4</button>
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '5' >5</button>
                <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '6' >6</button>
            </div>
        )
    }
}

更新:

我重写了组件以使用state下面@TomaszMularczyk 的回答作为参考使用react,但现在所有按钮都被切换,而不仅仅是点击按钮,如下所示:https : //jsfiddle.net/69z2wepo/183164/

4个回答

this 不会是 HTML 元素,而是 React Object 实例。

我会尝试更被动的方式来实现这一点并使用state

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

  toggleClass() {
    this.setState(prevState => ({ isDown: !prevState.isDown }));
  }

  render() {
    return (
      <button
        className={this.state.isDown ? "btnDown" : ""}
        onMouseDown={e => this.toggleClass(e)}
        onMouseUp={e => this.toggleClass(e)}
        {...this.props}
      />
    );
  }
}

export class Buttons extends React.Component {
  render() {
    return (
      <div className="btn-wrap">
        <Button value="1">1</Button>
        <Button value="2">2</Button>
        ....
      </div>
    );
  }
}

您可以制作自己的 Button 组件

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

  toggleClass() {
    this.setState(prevState => ({ isDown: !prevState.isDown }));
  }  

  render() {
    const className = `${this.state.isDown ? "btnDown" : ""}`;
    return <button className={className} onMouseDown={e => this.toggleClass(e)} value={this.props.value} {...this.props}>{this.props.children}</button>
  }
}

然后使用它们而不是 html 按钮 -

<div className="btn-wrap">
    <Button value = '1'>1</Button>
    <Button value = '2'>2</Button>
    <Button value = '3'>3</Button>
    <Button value = '+' onClick={e => console.log('+ clicked')}>3</Button>
    <Button value = '-' onClick={e => console.log('- clicked')}>3</Button>
</div>

而不是使用thisinside toggleClass,使用事件对象:

class Buttons extends React.Component {
    toggleClass(e) {
      if(e.target.classList.contains('btnDown')) {
        e.target.classList.remove('btnDown');
      } else {
        e.target.classList.add('btnDown');
      }
    }

    render() {
      return (
        <div className="btn-wrap">
          <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '1' >1</button>
          <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '2' >2</button>
          <button onMouseDown={(e) => this.toggleClass(e)} onMouseUp={(e) => this.toggleClass(e)} value = '3' >3</button>
        </div>
      )
    }
}

css 取自@Tomasz Mularczyk 的回答。

提琴手

我稍微重写了你的代码,它现在应该可以正常工作了:

class Buttons extends React.Component {

     constructor(props) {
         super(props);
         this.state = {
         isDown: null
      };

  }

  pressButton = (i) => {
    this.setState({ isDown: i });
  };
  releaseButton = () => {
    this.setState({ isDown: null });
  };

  render() {
    const { isDown } = this.state;
    const buttons = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, '+', '-'];

    return (
      <div className="btn-wrap">
        {buttons.map((button, i) => (
          <button
            className={`${isDown === i ? 'btnDown' : ''}`}
            onMouseDown={this.pressButton.bind(undefined, i)}
            onMouseUp={this.releaseButton}
            value={button}
          >
            {button}
          </button>
        ))}
      </div>
    )
  }
}

ReactDOM.render(
  <Buttons />,
  document.getElementById('container')
);`