事件处理与传播
事件处理与传播 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。
学习目标
交互写多了就会遇到「点一个按钮,两件事同时发生」:弹窗里的删除按钮把遮罩也关了,卡片上的小按钮把卡片也选中了。这一课讲清 React 事件模型:处理器怎么绑、事件怎么传播、表单提交的正确时机。读完你能拆掉这类误触发的连锁反应。
问题场景
课程卡片整块可点击(点击选中),卡片右下角又放了一个「删除」按钮:
<div className="card" onClick={() => select(course.id)}>
<h3>{course.title}</h3>
<button onClick={() => remove(course.id)}>删除</button>
</div>
点「删除」,卡片先被选中然后又被删掉——选中逻辑根本不该执行。原因是按钮在卡片内部:点击按钮时,事件沿着 DOM 树向上冒泡,先触发按钮自己的 onClick,再触发外层卡片的 onClick。两个处理器都执行了。
核心解释
React 的事件模型有三个要点:
一、绑定与命名。 JSX 里用驼峰属性绑事件:onClick、onChange、onSubmit,值是函数而不是字符串。React 把原生事件包了一层合成事件(SyntheticEvent),用法和原生一致:e.preventDefault() 阻止默认行为,e.stopPropagation() 阻止继续冒泡。
二、传播。 浏览器事件默认从最深的目标元素开始逐层向外冒泡。React 的 onClick 挂在冒泡阶段,所以「内层先执行、外层后执行」。想在内层截断,就在内层处理器里调 e.stopPropagation():
<button
onClick={(e) => {
e.stopPropagation(); // 事件不再冒泡到卡片
remove(course.id);
}}
>
删除
</button>
stopPropagation 不是随手加的保险丝——它会让外层完全感知不到这次点击。滥用它,其他依赖冒泡的全局逻辑(点击空白处关闭弹窗)就会失灵。正确姿势是:只在「内层动作与外层动作语义无关」时使用。
三、表单提交时机。 表单的回车键和提交按钮都会触发 submit 事件,正确入口只有一个:
<form onSubmit={(e) => { e.preventDefault(); submit(); }}>
<input />
<button type="submit">搜索</button>
</form>
preventDefault 阻止浏览器整页刷新,submit 保证「点按钮」和「按回车」走同一条路,不会漏分支。
示例拆解
实验区把三个易错场景摆在同一页,关键点如下:
- 卡片与删除按钮:切换「阻止冒泡」开关后,点删除按钮的行为不同——关闭时右侧日志显示「删除 + 选中卡片」两条记录,开启时只有「删除」;
- 事件日志面板:每次触发处理器就追加一条带序号的记录,冒泡顺序(内层先、外层后)肉眼可见;
- 搜索表单:
onSubmit统一处理「点提交」和「输入框按回车」两种触发方式,日志里都是同一个「提交」事件;输入框内的回车不会误触外层卡片——事件目标是输入框,冒泡路径不经过卡片的 onClick 所在元素(表单在卡片外); - 提交后的默认行为被
preventDefault拦下,页面没有刷新(刷新会丢掉整个实验状态)。
验证方式:开关切换前后各点一次删除按钮,对比日志条数。
动手任务
打开本课实验区,完成三个小改动:
- 给卡片加一个「收藏」按钮,同样阻止冒泡,验证选中逻辑不再误触发。
- 把表单提交按钮改成
type="button",观察提交不再触发——理解type的默认值是submit。 - 在日志面板里加一条时间戳,观察同一连串触发的时间间隔,确认都是同一瞬间完成(不是异步排队)。
常见错误
- 忘记 preventDefault:表单提交后页面整页刷新,所有状态归零;
onSubmit第一行就写上。 - 内外层处理器语义耦合:外层靠「没拦住」才不执行动作,内层一改逻辑就连锁爆炸;该拦就显式
stopPropagation。 - 按钮没写 type:
<button>默认type="submit",放在 form 里点它会顺手触发提交;非提交按钮写type="button"。 - 用 onClick 监听回车:在 input 上挂
onKeyDown判断 Enter 而不用表单 onSubmit,会漏掉「点提交按钮」这条路;提交统一交给 onSubmit。
检查与复盘
完成下方检查题确认理解。自查清单:
- 能画出一个三层嵌套结构的冒泡路径,说出处理器执行顺序
- 知道
stopPropagation和preventDefault各管什么、什么时候用 - 表单交互统一走 onSubmit,按钮显式声明 type
参考资料
- React 官方文档:响应事件 —— 事件绑定与 event 对象
- React 官方文档:事件传播 —— 冒泡、stopPropagation 与传播阶段的官方说明
- React 官方文档:用事件传播添加或移除监听 —— 冒泡与 stopPropagation 的官方说明
读完这一课了?
标记完成后,工作台会安排接下来的学习。