事件处理
你已经构建了一个按钮。现在它需要在有人点击时真正做一些事情,比如保存表单、打开菜单或删除项目。React 处理事件的方式和处理其他所有事情一样:通过 props。与你在 JavaScript 事件章节 中使用的 addEventListener 不同,你直接将一个函数传递给想要监听的元素上的 prop。核心思想是一样的,都是在某个事件发生时运行的函数,但 React 有自己独特的方式来连接它们。
附加事件处理函数
function SaveButton() {
function handleClick() {
console.log('clicked')
}
return <button onClick={handleClick}>Save</button>
}事件 props 用驼峰命名法命名,与它们监听的事件相匹配:onClick 用于点击事件,onChange 用于字段值变化,onSubmit 用于表单提交。你在元素上写上 prop,并给它一个要运行的函数。
handleClick 定义在组件内部,然后传递给 onClick。每当按钮被点击时,React 就会调用它。你传的是函数的名称 handleClick。如果写成 handleClick(),它会在渲染期间立即运行。你要做的是把函数交给 React 在稍后运行,而不是现在自己运行它。
当你需要了解发生了什么的细节时,React 会传给你的处理函数一个**事件对象**,包含你从 addEventListener 那里熟悉的那些属性,比如 target、preventDefault() 等。用一个参数来捕捉它,按惯例叫做 event:
function SearchBox() {
function handleChange(event) {
console.log(event.target.value)
}
return <input onChange={handleChange} />
}event.target 是事件触发的元素,event.target.value 是字段中的当前文本。只有当处理函数真正需要这些信息时,你才需要用到事件对象。按钮的 onClick 通常不需要。
最常见的错误
因为处理函数是你传给 prop 的一个函数,这是一个容易让几乎所有人都踩的坑:
// 错误:在组件渲染时立即调用 handleClick
<button onClick={handleClick()}>Save</button>
// 正确:传递函数本身,React 在点击时调用它
<button onClick={handleClick}>Save</button>圆括号是唯一的区别。handleClick() 在渲染期间立即运行函数,无论它返回什么(通常是 undefined)都会被赋给 onClick。handleClick 把函数本身交给 React,让它在点击真正发生时调用。如果一个处理函数似乎在页面加载时自动触发了,通常就是这个原因。
将处理函数作为 props 传递
处理函数不一定要和它要附加的元素在同一个组件中。你可以在父组件中定义它,然后像传递其他值一样把它作为 prop 传给子组件:
function SaveButton({ onSave }) {
return <button onClick={onSave}>Save</button>
}
function Form() {
function handleSave() {
console.log('saved')
}
return <SaveButton onSave={handleSave} />
}Form 拥有 handleSave,并通过 onSave prop 将它传给 SaveButton。SaveButton 不知道也不关心这个函数做什么,它只负责把它连接到 onClick。这就是小的可复用组件上的一个点击事件如何触发应用中更高层的逻辑的方式,那里更接近这些逻辑需要的状态或数据。
阻止默认行为
某些事件带有浏览器的默认行为,提交表单是你首先会遇到的。默认情况下,提交表单会重新加载页面,这会丢弃你的组件正在做的任何事情。在处理函数中调用 event.preventDefault() 来阻止这种行为:
function SignupForm() {
function handleSubmit(event) {
event.preventDefault()
console.log('form submitted')
}
return (
<form onSubmit={handleSubmit}>
<input type="email" />
<button type="submit">Sign up</button>
</form>
)
}把 onSubmit 附加到 <form> 本身,而不是 onClick 到按钮。这样在字段中按 Enter 也会提交表单,不只是点击按钮。
onClick 和 onChange,你给它们一个要运行的函数,而不是运行它的结果。写成 onClick={handleClick},永远不要写 onClick={handleClick()}。 当处理函数需要了解发生了什么的细节时,用一个名叫 event 的参数来捕捉它们。
接下来:条件渲染,组件返回的内容开始依赖于它所拥有的数据。

