添加事件回调
<button onClick={handleClick}>Click Me</button>
将回调作为 prop 传入
可以将回调函数作为 prop 传入给子组件。
function Button({onClick, children}) {
return (
<button onClick={onClick}>{children}</button>
)
}
function App() {
return (
<div className="container">
<Button onClick={() => console.log('Clicked')}>Click Me</Button>
</div >
)
}
自定义回调函数命名
可以给组件使用自定义的回调函数命名。一般情况下,都以 on
开头。
事件冒泡
当子组件触发了 click 事件后,父组件也能捕获到该事件。
function App() {
return (
<div className='container'>
<div className='block' onClick={() => console.log('Click block')}>
<button onClick={() => console.log('Click button')}>Button</button>
</div>
</div >
)
}
stopPropagation()
可以在子组件中调用 stopPropagation()
来阻止事件继续向上冒泡:
function App() {
function handleButtonClick(e) {
e.stopPropagation()
console.log('Click button')
}
return (
<div className='container'>
<div className='block' onClick={() => console.log('Click block')}>
<button onClick={handleButtonClick}>Button</button>
</div>
</div >
)
}
事件捕获
可以在父组件上设置 onClickCapture
属性来使用事件捕获的方式,无论子组件有没有设置 stopPropagation()
,父组件总能率先捕捉到事件。
🔹 事件捕获与事件冒泡正好相反,因此父组件可以率先被捕获到
function App() {
function handleBlockClick(e) {
console.log('Click Block')
}
function handleButtonClick(e) {
e.stopPropagation()
console.log('Click button')
}
return (
<div className='container'>
{ /* onClickCapture 的函数会被率先执行 */ }
<div className='block' onClickCapture={handleBlockClick}>
<button onClick={handleButtonClick}>Button</button>
</div>
</div >
)
}
手动传入回调来代替冒泡
比起默认实现的事件冒泡,可以通过手动传入回调的方法来实现:
function Child({ onClick, children }) {
function handleClick(e) {
// 先阻止继续冒泡
e.stopPropagation()
// 手动调用传入的回调
onClick()
}
<button onClick={handleClickl}>{children}</button>
}
这样做的好处就是不仅子组件可以先做一些处理,同时父组件可以继续执行额外的一些工作。
比起自动冒泡,这种做法能够更好地做到追踪。
阻止默认行为
点击在表单中的按钮会默认提交并刷新页面,使用 preventDefault()
来阻止默认提交行为
<form onSubmit={e => {
e.preventDefault();
alert('Submitting!');
}}>
<input />
<button>Send</button>
</form>