应用程序中的大部分行为都围绕着事件展开。用户在注册表单中输入值?事件。用户点击提交按钮?另一个事件。事件可以通过多种方式触发,我们构建应用程序来监听这些事件,以便做出相应的操作。
根据您现有的 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 事件的包装器。我们深入研究了创建事件监听器的过程,以便它们附加到合成事件,并确保在触发这些事件时组件会更新。
其他资源
- 处理事件 – React 文档
- 合成事件 – React 文档,包括所有事件类型
- 在学习 Redux 之前需要了解的 5 个基本 React 概念 – Chris Nwamba 在本系列的第二部分中提供了 React 事件处理的概述
我对 React 了解得越多,就越不明白为什么人们如此喜爱它。我理解它背后的理念,但这个理念的实际实现却是一团糟。
我同意你的观点,Klopfer,我也无法理解这一点。理念很棒,但实现却相当复杂,通常令人困惑。我创建了几个 React 应用程序,但最终都放弃了,希望永远不再使用。我更倾向于 Vue,在我看来,它更直接,更直观。
作为一个在部分使用 React 和部分使用 jQuery 以及自制代码的应用程序上工作的人,我可以说我们代码库中 React 部分