这一节的内容将学到:
- 编写事件处理函数的不同方式
- 如何从父组件传递事件处理逻辑
- 事件是如何传递的,如何阻止事件传递
添加事件处理函数
- 定义一个函数
- 将这个函数作为JSX标签属性传递给组件
export default function Button() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
也可以通过内联到JSX标签来定义事件处理函数:
<button onClick={function handleClick() {
alert('You clicked me!');
}}>
需要注意的地方⚠️:
传递函数(正确) | 调用函数(错误❌) |
<button onClick={handleClick}> | <button onClick={handleClick()}> |
在事件处理函数中读取属性
function AlertButton({ message, children }) {
return (
<button onClick={() => alert(message)}>
{children}
</button>
);
}
export default function Toolbar() {
return (
<div>
<AlertButton message="Playing!">
Play Movie
</AlertButton>
<AlertButton message="Uploading!">
Upload Image
</AlertButton>
</div>
);
}
将事件处理函数作为属性传递:
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
function PlayButton({ movieName }) {
function handlePlayClick() {
alert(`Playing ${movieName}!`);
}
return (
<Button onClick={handlePlayClick}>
Play "{movieName}"
</Button>
);
}
function UploadButton() {
return (
<Button onClick={() => alert('Uploading!')}>
Upload Image
</Button>
);
}
export default function Toolbar() {
return (
<div>
<PlayButton movieName="Kiki's Delivery Service" />
<UploadButton />
</div>
);
}
记住,JavaScript中函数是可以作为变量传递的。
export default function App() {
return (
<Toolbar
onPlayMovie={() => alert('Playing!')}
onUploadImage={() => alert('Uploading!')}
/>
);
}
function Toolbar({ onPlayMovie, onUploadImage }) {
return (
<div>
<Button onClick={onPlayMovie}>
Play Movie
</Button>
<Button onClick={onUploadImage}>
Upload Image
</Button>
</div>
);
}
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
事件处理函数也可以通过变量名进行传递,例如上面代码里的onPlayMovie和onUploadImage
事件传递
和DOM事件一样,React事件也会“冒泡”和“传递”。
export default function Toolbar() {
return (
<div className="Toolbar" onClick={() => {
alert('You clicked on the toolbar!');
}}>
<button onClick={() => alert('Playing!')}>
Play Movie
</button>
<button onClick={() => alert('Uploading!')}>
Upload Image
</button>
</div>
);
}
React的所有事件都会传递,出了onScroll,这个事件只会在绑定节点上触发。
阻止事件冒泡的代码写法:
function Button({ onClick, children }) {
return (
<button onClick={e => {
e.stopPropagation();
onClick();
}}>
{children}
</button>
);
}
export default function Toolbar() {
return (
<div className="Toolbar" onClick={() => {
alert('You clicked on the toolbar!');
}}>
<Button onClick={() => alert('Playing!')}>
Play Movie
</Button>
<Button onClick={() => alert('Uploading!')}>
Upload Image
</Button>
</div>
);
}
事件捕获:
在某些业务场景下需要捕获当前元素的所有子元素上触发的事件,例如数据埋点的需求,这个时候需要用到事件捕获。
<div onClickCapture={() => { /* this runs first */ }}>
<button onClick={e => e.stopPropagation()} />
<button onClick={e => e.stopPropagation()} />
</div>
在事件后面加上Capture可以实现事件捕获。
function Button({ onClick, children }) {
return (
<button onClick={e => {
e.stopPropagation();
onClick();
}}>
{children}
</button>
);
}
上面这段代码可以确保在按钮被点击时不会影响到父组件或者其他上层组件的事件处理。
阻止默认事件行为:
export default function Signup() {
return (
<form onSubmit={e => {
e.preventDefault();
alert('Submitting!');
}}>
<input />
<button>Send</button>
</form>
);
}
可以阻止默认的表单提交行为。