在 React 中,由于事件处理逻辑通常位于父组件,而事件触发于子组件(如按钮点击),因此需要将事件处理函数从父组件作为 props 传递给子组件。这是 React 数据和逻辑自上而下流动的典型体现。
以下是几种常见的传递方式:
1. 通过 Props 传递回调函数(最常用)
这是最基础、最推荐的方式。父组件定义事件处理函数,并通过 props 传递给子组件。
// 子组件
function Button({ onClick, children }) {
return (
<button onClick={onClick}>
{children}
</button>
);
}
// 父组件
function Parent() {
const handleClick = () => {
console.log('按钮被点击了!');
};
return (
<div>
<Button onClick={handleClick}>点击我</Button>
</div>
);
}
2. 传递参数给子组件的事件处理器
有时需要在子组件中触发事件时传递额外数据。可以在父组件中使用箭头函数包裹,或在子组件中调用时传参。
方式一:父组件使用箭头函数传参
function Parent() {
const handleItemClick = (id) => {
console.log(`项目 ${id} 被点击`);
};
return (
<ul>
<li><Button onClick={() => handleItemClick(1)}>项目 1</Button></li>
<li><Button onClick={() => handleItemClick(2)}>项目 2</Button></li>
</ul>
);
}
方式二:子组件在触发时传参
// 子组件
function Item({ id, onItemClick }) {
return (
<div onClick={() => onItemClick(id)}>
项目 {id}
</div>
);
}
// 父组件
function Parent() {
const handleItemClick = (id) => {
console.log(`项目 ${id} 被点击`);
};
return (
<div>
<Item id={1} onItemClick={handleItemClick} />
<Item id={2} onItemClick={handleItemClick} />
</div>
);
}
3. 使用 useCallback 优化(避免不必要的重渲染)
当子组件是 React.memo 优化过的纯组件时,频繁传递新的函数引用会导致子组件不必要的重渲染。可以使用 useCallback 缓存事件处理函数。
import React, { useCallback } from 'react';
function Parent() {
const handleSave = useCallback(() => {
console.log('保存数据');
}, []); // 空依赖数组,函数不会改变
return (
<div>
<ExpensiveChild onSave={handleSave} />
</div>
);
}
4. 通过 Context 传递(适用于深层嵌套)
当组件层级较深,逐层传递 props 显得繁琐时(“props drilling”),可以使用 React Context。
// 创建 Context
const EventContext = React.createContext();
// 父组件(提供者)
function Parent() {
const handleClick = () => {
console.log('深层组件触发点击');
};
return (
<EventContext.Provider value={{ handleClick }}>
<Child />
</EventContext.Provider>
);
}
// 深层子组件(消费者)
function DeepChild() {
const { handleClick } = React.useContext(EventContext);
return <button onClick={handleClick}>深层按钮</button>;
}
5. 使用自定义 Hook 封装逻辑
将事件处理逻辑封装到自定义 Hook 中,提高复用性。
// 自定义 Hook
function useClickHandler() {
const handleClick = () => {
console.log('通用点击处理');
};
return { handleClick };
}
// 组件中使用
function MyComponent() {
const { handleClick } = useClickHandler();
return <Button onClick={handleClick}>点击</Button>;
}
总结
- 首选方式:通过
props传递回调函数。 - 性能优化:配合
useCallback和React.memo避免不必要渲染。 - 深层传递:使用
Context避免 props drilling。 - 逻辑复用:使用自定义 Hook 封装事件逻辑。
核心思想是:React 鼓励将状态和逻辑保留在上层组件,通过 props 将行为(函数)向下传递,保持组件的解耦和可预测性。
THE END


