在这个React教程中,我们将了解React中HTML元素的事件处理程序,如按钮和输入元素。你将学习如何使用按钮的onClick事件以及如何定义和使用不同种类的事件处理程序。基本上我们将经历三种事件处理程序:事件处理程序、内联事件处理程序和回调事件处理程序。
React中的事件处理程序
首先,我们将从React中的一个按钮的例子开始,了解具体的onClick事件处理程序。这是关于如何在React中用事件处理程序(也叫事件处理函数或处理程序)来处理事件的最基本的例子。一个按钮有一个onClick属性,接收一个函数。这个函数在每次事件被触发时被调用(这里:当点击按钮时)。
import React from 'react';
function App() {
function handleClick() {
console.log('Button click ...');
}
return (
<div>
<button type="button" onClick={handleClick}>
Event Handler
</button>
</div>
);
}
对于其他属性,如onChange(onChange事件处理程序)和onSubmit(onSubmit事件处理程序),它的作用也类似。对于初学者来说,往往onClick不起作用,因为他们没有传递一个函数,而是直接在JSX中调用函数。例如,在下一个版本中,事件处理程序只在第一次渲染组件时被调用一次。其他每一次点击都不会调用事件处理函数,因为函数的返回值被用于onClick属性,而不是函数本身。所以没有什么可调用的;除非该函数返回另一个函数。
import React from 'react';
function App() {
function handleClick() {
console.log('Button click ...');
}
// don't do this
return (
<div>
<button type="button" onClick={handleClick()}>
Event Handler
</button>
</div>
);
}
通过使用一个JavaScript箭头函数,事件处理函数可以变得更加简洁。但这是一个可选的步骤。就个人而言,我喜欢把事件处理程序作为箭头函数。
import React from 'react';
function App() {
const handleClick = () => {
console.log('Button click ...');
};
return (
<div>
<button type="button" onClick={handleClick}>
Event Handler
</button>
</div>
);
}
但一旦在React组件中的事件处理程序增多,通过再次给它们提供function 语句,使它们与其他变量更有区别也是不错的:
import React from 'react';
function App() {
const user = {
id: '123abc',
username: 'Robin Wieruch',
};
function handleUserSignIn() {
// do something
}
function handleUserSignUp() {
// do something
}
function handleUserSignOut() {
// do something
}
...
}
毕竟,onClick事件的事件处理程序应该实现一些商业逻辑。在这个例子中,React的useState Hook被用来通过onClick按钮事件来更新一些状态。
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
Count: {count}
<button type="button" onClick={handleClick}>
Increase Count
</button>
</div>
);
}
下一个例子向你展示了一个输入字段而不是一个按钮。在这里,我们使用的是实际的事件,它总是作为第一个参数传递给事件处理函数。该事件是一个来自React的合成事件,它本质上封装了本地HTML事件,并在此基础上添加了一些功能。每次有人用事件的目标属性在输入框中输入时,这个事件就会给你输入框的值。
import React from 'react';
function App() {
const [text, setText] = React.useState('');
function handleChange(event) {
setText(event.target.value);
}
return (
<div>
<input type="text" onChange={handleChange} />
{text}
</div>
);
}
以前我们没有使用这个事件,因为在我们的按钮例子中我们不需要它。但在输入栏的例子中,我们需要它。最后但并非最不重要的是,不要忘记把值传递给输入元素,使它成为一个受控的组件。
import React from 'react';
function App() {
const [text, setText] = React.useState('');
function handleChange(event) {
setText(event.target.value);
}
return (
<div>
<input type="text" value={text} onChange={handleChange} />
{text}
</div>
);
}
这就是事件处理程序的简要介绍。让我们学习一下React中更高级的处理程序。
React中的内联事件处理程序
内联事件处理程序,也叫内联处理程序,通过在JSX中直接使用事件处理程序,给我们提供了很多新的选择。
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
return (
<div>
Count: {count}
<button
type="button"
onClick={function() {
setCount(count + 1);
}}
>
Increase Count
</button>
</div>
);
}
虽然在JJSX中使用普通的函数语句是很冗长的。因此,JavaScript的箭头函数就派上了用场,可以更简洁地定义内联处理程序。
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
return (
<div>
Count: {count}
<button
type="button"
onClick={() => setCount(count + 1)}
>
Increase Count
</button>
</div>
);
}
一般来说,开发者都是懒人,所以经常使用内联事件处理程序来避免在JJSX之外进行额外的函数声明。然而,这将大量的商业逻辑移入JJSX中,使得它的可读性、可维护性和易错性降低。就我个人而言,我喜欢在没有内联事件处理程序的情况下保持JSX的简洁,而在JSX之外声明事件处理程序。
内联处理程序也被用来传递一个参数给一个更通用的处理程序,这个处理程序被定义在JSX之外。
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
function handleCount(delta) {
setCount(count + delta);
}
return (
<div>
Count: {count}
<button type="button" onClick={() => handleCount(1)}>
Increase Count
</button>
<button type="button" onClick={() => handleCount(-1)}>
Decrease Count
</button>
</div>
);
}
这样一来,也可以同时传递事件和参数。尽管在这个例子中不需要,但你在未来肯定会遇到这样或那样的情况,你会需要这个事件(例如,React Forms的preventDefault)。
import React from 'react';
function App() {
const [count, setCount] = React.useState(0);
function handleCount(event, delta) {
setCount(count + delta);
}
return (
<div>
Count: {count}
<button type="button" onClick={event => handleCount(event, 1)}>
Increase Count
</button>
<button type="button" onClick={event => handleCount(event, -1)}>
Decrease Count
</button>
</div>
);
}
所以只要你需要传递事件和参数,例如当你需要一个额外的参数给你的onClick事件时,内联事件处理程序可能会帮助你。然后在JSX之外的更通用的事件处理程序可以使用这个额外的参数。
React中的回调事件处理程序
最后但并非最不重要的是,有回调事件处理程序或简称为回调处理程序。当一个子组件需要与父组件沟通时,它们就会被使用。由于React道具只在组件树上传递,回调处理程序,其核心是一个函数,被用来向上通信。
import React from 'react';
function App() {
const [text, setText] = React.useState('');
// 1
function handleTextChange(event) {
setText(event.target.value); // 3
}
return (
<div>
<MyInput inputValue={text} onInputChange={handleTextChange} />
{text}
</div>
);
}
// 2
function MyInput({ inputValue, onInputChange }) {
return (
<input type="text" value={inputValue} onChange={onInputChange} />
);
}
回调处理程序被定义在某处(1),在其他地方使用(2),但会回调到其定义的地方(3)。这样一来,就有可能从子组件到父组件进行通信。一个回调处理程序通过React道具向下传递,并在函数被调用时向上通信。
你已经了解了React的事件处理程序、内联事件处理程序和回调事件处理程序,以及如何在按钮的onClick事件和输入框的onChange事件中使用它们。还有其他的事件处理程序,例如表单元素的onSubmit,实际上需要该事件来阻止本地浏览器的行为。总之,所有这些事件处理程序都有其特定的目的。你的目标应该是保持你的代码的可读性和可维护性,所以让你和你的团队在这里为React的代码风格达成一致。你可以在GitHub上找到一个React事件处理程序的乐园。