在 React 中使用事件

Avatar of Kingsley Silas
Kingsley Silas

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

应用程序中的大部分行为都围绕着事件展开。用户在注册表单中输入值?事件。用户点击提交按钮?另一个事件。事件可以通过多种方式触发,我们构建应用程序来监听这些事件,以便做出相应的操作。

根据您现有的 JavaScript 经验,您可能已经非常熟悉事件处理。但是,React 有一种独特的方式来处理它们。React 不会直接针对 DOM 事件,而是将它们包装在自己的事件包装器中。但我们稍后会详细介绍。

让我们一起了解如何在 React 中创建、添加和监听事件。

创建事件

我们将从创建一个包含输入框和按钮的表单开始。当输入值时,将触发一个事件。按钮用于调用一个函数,该函数将反转该值。

以下是它的工作原理

  • 一个空的输入字段允许用户输入文本。
  • 当在输入框中输入值时,会触发 onChange 事件。这将调用一个函数——handleChange()——用于设置输入框的新状态。
  • 当点击“反转文本”按钮时,会触发另一个事件。这将调用一个函数——handleReverse()——来设置 reversedText 的新状态。

以下是转换为代码后的样子

class App extends React.Component {
  state = {
    /*  Initial State */
    input: "",
    reversedText: ""
  };

  /* handleChange() function to set a new state for input */
  handleChange = event => {
    const value = event.target.value;
    this.setState({
      input: value
    });
  };

  /* handleReverse() function to reverse the input and set that as new state for reversedText */
  handleReverse = event => {
    event.preventDefault();
    const text = this.state.input;
    this.setState({
      reversedText: text
        .split("")
        .reverse()
        .join("")
    });
  };

  render() {
    return (
      <React.Fragment>
        { /* handleReverse() is called when the form is submitted */ }
        <form onSubmit={this.handleReverse}>
          <div>
            { /* Render input entered */}
            <label>Text: {this.state.input}</label>
          </div>
          <div>
           { /* handleChange() is triggered when text is entered */ }
            <input
              type="text"
              value={this.state.input}
              onChange={this.handleChange}
              placeholder="Enter a text"
            />
          </div>
          <div>
            <button>Reverse Text</button>
          </div>
        </form>
        { /* Render reversed text */}
        <p>Reversed Text: {this.state.reversedText}</p>
      </React.Fragment>
    );
  }
}}

查看 CodePen 上 Kingsley Silas Chijioke (@kinsomicrote) 编写的 React 事件笔——表单 React Event Pen – form

监听组件事件

假设您有一个这样的组件;

class IncrementButton extends React.Component{
  render() {
    return (
      <React.Fragment>
        <button>+</button>
      </React.Fragment>
    )
  }
}

像这样将其包含在您的 App 组件中是否有效?

class App extends React.Component{
  state = {
    count: 0
  }

  handleIncrement = (event) => {
    this.setState({ count: this.state.count + 1})
  }

  render() {
    return(
      <React.Fragment>
        <h1>{this.state.count}</h1>
        <IncrementButton onClick={this.handleIncrement} />
      </React.Fragment>
    )
  }
}

不会,因为它只能监听 DOM 元素上的事件。我们在文章开头提到了这一点,但 React 组件是 DOM 元素的包装器。这意味着我们实际上有一个需要穿过的层才能监听事件。

解决此问题的办法是将事件处理程序作为 prop 传递给子组件。然后,该 prop 会向下传递到 click 事件,作为属性,如下所示

class IncrementButton extends React.Component{
  render() {
    return (
      <React.Fragment>
        <button onClick={this.props.increaseButton}>+</button>
      </React.Fragment>
    )
  }
}

class App extends React.Component{
  state = {
    count: 0
  }

  handleIncrement = (event) => {
    this.setState({ count: this.state.count + 1})
  }

  render() {
    return(
      <React.Fragment>
        <h1>{this.state.count}</h1>
        <IncrementButton increaseButton={this.handleIncrement} />
      </React.Fragment>
    )
  }
}

查看 CodePen 上 Kingsley Silas Chijioke (@kinsomicrote) 编写的 React 事件笔——组件事件 React Event Pen – Component Events

您可以使用 无状态函数组件 代替。

const IncrementButton = (props) => {
  return (
    <React.Fragment>
      <button onClick={props.increaseButton}>+</button>
    </React.Fragment>
  )
}

添加事件监听器

有时您可能希望使用某些在组件挂载时触发的 DOM 事件。让我们使用 resize 事件来演示这一点——我们希望在窗口大小调整时查看窗口的宽度。

class App extends React.Component{
  state = {
    windowWith: window.innerWidth
  }

  handleResize = (event) => {
    this.setState({ windowWith: window.innerWidth })
  }

  render() {
    return(
      <React.Fragment>
        <h1>Window Width</h1>
        <h1>{this.state.windowWith}</h1>
      </React.Fragment>
    )
  }
}

如果我们创建一个组件并像下面这样尝试,则不会触发事件。我们需要添加事件监听器(在本例中为 handleResize())和事件类型,如下所示

class App extends React.Component{
  state = {
    windowWith: window.innerWidth
  }

  handleResize = (event) => {
    this.setState({ windowWith: window.innerWidth })
  }
  
  componentDidMount() {
    window.addEventListener('resize', this.handleResize)
  }

  componentDidUnmount() {
    window.removeEventListener('resize', this.handleResize)
  }

  render() {
    return(
      <React.Fragment>
        <h1>Window Width</h1>
        <h1>{this.state.windowWith}</h1>
      </React.Fragment>
    )
  }
}

查看 CodePen 上 Kingsley Silas Chijioke (@kinsomicrote) 编写的 React 事件笔——addEventListener React Event Pen – addEventListener

现在,事件监听器将在组件挂载时添加。这意味着我们的组件正在主动监听浏览器窗口,并在其更新时显示其宽度。

总结

好的,我们在很小的篇幅内涵盖了相当多的内容。我们了解到 React 不会直接连接到 DOM 事件,而是连接到 合成事件,它们是 DOM 事件的包装器。我们深入研究了创建事件监听器的过程,以便它们附加到合成事件,并确保在触发这些事件时组件会更新。

其他资源