事件
你已经构建了一个按钮。现在它需要在用户点击它时真正做一些事情,比如保存表单、打开菜单或删除项目。React 处理事件的方式和处理其他所有东西的方式一样:通过属性。与其像在 JavaScript 事件章节 中那样调用 addEventListener,不如直接把一个函数传给你要监听的元素的属性。核心思想是一样的——一个函数在某事发生时运行——但在 React 中,连接函数的方式是独特的模式。
添加事件处理程序
function SaveButton() {
function handleClick() {
console.log('clicked')
}
return <button onClick={handleClick}>Save</button>
}事件属性采用 camelCase 命名,与它们监听的事件相对应:onClick 用于点击事件,onChange 用于字段值改变,onSubmit 用于表单提交。你在元素上写上这个属性,给它传一个要运行的函数。
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 经常不需要。
最常见的错误
因为处理程序是你传给属性的函数,这个错误几乎每个人都会犯过一次:
// 错误:在组件渲染时立即调用 handleClick
<button onClick={handleClick()}>Save</button>
// 正确:传递函数本身,React 在点击时调用它
<button onClick={handleClick}>Save</button>括号就是全部区别。handleClick() 在渲染期间立即运行函数,它返回的任何东西(通常是 undefined)就是最终传给 onClick 的值。handleClick 把函数本身交给 React,让它在点击真正发生时调用。 如果一个处理程序似乎在页面加载的那一刻就自动触发了,几乎总是因为这个原因。
将处理程序作为属性传递给子组件
处理程序不一定要和附加它的元素在同一个组件里。你可以在父组件中定义它,然后像传递其他值一样把它作为属性传给子组件:
function SaveButton({ onSave }) {
return <button onClick={onSave}>Save</button>
}
function Form() {
function handleSave() {
console.log('saved')
}
return <SaveButton onSave={handleSave} />
}Form 拥有 handleSave,把它以 onSave 属性名传给 SaveButton。SaveButton 不知道也不在乎这个函数做什么,它只是把它连接到 onClick。这就是小的、可复用组件上的点击事件如何触发应用程序更高层的逻辑的方式,靠近那些逻辑需要的 state 或数据。
阻止默认行为
有些事件自带浏览器行为,表单提交是你首先会遇到的。默认情况下,提交表单会重新加载页面,这会清除你的组件正在做的任何事情。在处理程序中调用 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 的参数来接收它。 接下来:条件渲染,组件返回的内容开始取决于它拥有的数据。

