這一節的内容将學到:
- 編寫事件處理函數的不同方式
- 如何從父元件傳遞事件處理邏輯
- 事件是如何傳遞的,如何阻止事件傳遞
添加事件處理函數
- 定義一個函數
- 将這個函數作為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>
);
}
可以阻止預設的表單送出行為。