react 事件
使用 React 可以在 JSX 中添加 事件处理函数。其中事件处理函数为自定义函数,它将在响应交互(如点击、悬停、表单输入框获得焦点等)时触发。
添加事件处理函数
如需添加一个事件处理函数,需要先定义一个函数,然后 将其作为 prop 传入 合适的 JSX 标签。例如,这里有一个没绑定任何事件的按钮:
- 在
Button组件 内部 声明一个名为handleClick的函数。 - 实现函数内部的逻辑(使用
alert来显示消息)。 - 添加
onClick={handleClick}到<button>JSX 中。
export default function Button() { function handleClick() { alert('你点击了我!'); }
return ( <button onClick={handleClick}> 点我 </button> );}你可以定义 handleClick 函数然后 将其作为 prop 传入 <button>。其中 handleClick 是一个 事件处理函数 。事件处理函数有如下特点:
- 通常在你的组件 内部 定义。
- 名称以
handle开头,后跟事件名称。
按照惯例,通常将事件处理程序命名为
handle,后接事件名。你会经常看到onClick={handleClick},onMouseEnter={handleMouseEnter}等。
或者,你也可以在 JSX 中定义一个内联的事件处理函数:
<button onClick={function handleClick() { alert('你点击了我!');}}>或者,直接使用更为简洁箭头函数:
<button onClick={() => { alert('你点击了我!');}}>以上所有方式都是等效的。当函数体较短时,内联事件处理函数会很方便。
在事件处理函数中读取 props
由于事件处理函数声明于组件内部,因此它们可以直接访问组件的 props。示例中的按钮,当点击时会弹出带有 message prop 的 alert:
function AlertButton({ message, children }) { return ( <button onClick={() => alert(message)}> {children} </button> );}export default function Toolbar() { return ( <div> <AlertButton message="正在播放!"> 播放电影 </AlertButton> </div> );}将事件处理函数作为 props 传递
当你的组件支持多种交互时,你可以根据不同的应用程序命名事件处理函数 prop。例如,一个 Toolbar 组件接收 onPlayMovie 和 onUploadImage 两个事件处理函数:
export default function App() { return ( <Toolbar onPlayMovie={() => alert('正在播放!')} onUploadImage={() => alert('正在上传!')} /> );}
function Toolbar({ onPlayMovie, onUploadImage }) { return ( <div> <Button onClick={onPlayMovie}> 播放电影 </Button> <Button onClick={onUploadImage}> 上传图片 </Button> </div> );}
function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> );}命名事件处理函数 prop
内置组件(<button> 和 <div>)仅支持 浏览器事件名称,例如 onClick。但是,当你构建自己的组件时,你可以按你个人喜好命名事件处理函数的 prop。
按照惯例,事件处理函数 props 应该以
on开头,后跟一个大写字母。
例如,一个 Toolbar 组件接收 onPlayMovie 和 onUploadImage 两个事件处理函数:
export default function App() { return ( <Toolbar onPlayMovie={() => alert('正在播放!')} onUploadImage={() => alert('正在上传!')} /> );}
function Toolbar({ onPlayMovie, onUploadImage }) { return ( <div> <Button onClick={onPlayMovie}> 播放电影 </Button> <Button onClick={onUploadImage}> 上传图片 </Button> </div> );}
function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> );}App 组件并不需要知道 Toolbar 将会对 onPlayMovie 和 onUploadImage 做 什么 。上述示例是 Toolbar 的实现细节。其中,Toolbar 只是将它们作为 onClick 处理函数传递给了 Button 组件,事件由 Button 组件触发。
事件传播
事件处理函数还将捕获任何来自子组件的事件。通常,我们会说事件会沿着树向上“冒泡”或“传播”:它从事件发生的地方开始,然后沿着树向上传播。
export default function Toolbar() { return ( <div className="Toolbar" onClick={() => { alert('你点击了 toolbar !'); }}> <button onClick={() => alert('正在播放!')}> 播放电影 </button> <button onClick={() => alert('正在上传!')}> 上传图片 </button> </div> );}如果你点击任一按钮,它自身的 onClick 将首先执行,然后父级 <div> 的 onClick 会接着执行。因此会出现两条消息。如果你点击 toolbar 本身,将只有父级 <div> 的 onClick 会执行。
在 React 中所有事件都会传播,除了
onScroll,它仅适用于你附加到的 JSX 标签。
阻止传播
事件处理函数接收一个 事件对象 作为唯一的参数。按照惯例,它通常被称为 e ,代表 “event”(事件)。你可以使用此对象来读取有关事件的信息。
这个事件对象还允许你阻止传播。如果你想阻止一个事件到达父组件,你需要像下面 Button 组件那样调用 e.stopPropagation() :
function Button({ onClick, children }) { return ( <button onClick={e => { e.stopPropagation(); // onClick(); }}> {children} </button> );}
export default function Toolbar() { return ( <div className="Toolbar" onClick={() => { alert('你点击了 toolbar !'); }}> <Button onClick={() => alert('正在播放!')}> 播放电影 </Button> <Button onClick={() => alert('正在上传!')}> 上传图片 </Button> </div> );}当你点击按钮时:
-
React 调用了传递给
<button>的onClick处理函数。 -
定义在
Button中的处理函数执行了如下操作:- 调用
e.stopPropagation(),阻止事件进一步冒泡。 - 调用
onClick函数,它是从Toolbar组件传递过来的 prop。
- 调用
-
在
Toolbar组件中定义的函数,显示按钮对应的 alert。 -
由于传播被阻止,父级
<div>的onClick处理函数不会执行。
由于调用了 e.stopPropagation(),点击按钮现在将只显示一个 alert(来自 <button>),而并非两个(分别来自 <button> 和父级 toolbar <div>)。点击按钮与点击周围的 toolbar 不同,因此阻止传播对这个 UI 是有意义的。
阻止默认行为
某些浏览器事件具有与事件相关联的默认行为。例如,点击 <form> 表单内部的按钮会触发表单提交事件,默认情况下将重新加载整个页面,可以调用事件对象中的 e.preventDefault() 来阻止这种情况发生:
export default function Signup() { return ( <form onSubmit={e => { e.preventDefault(); alert('提交表单!'); }}> <input /> <button>发送</button> </form> );}
e.stopPropagation()阻止触发绑定在外层标签上的事件处理函数。e.preventDefault()阻止少数事件的默认浏览器行为。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!














