DOM 事件与观察器
事件描述某次发生的交互,观察器描述某类状态的变化。正确设计先选信号,再界定传播范围、异步回调归属与清理,最后检查自己的写入会不会反过来制造同一信号。
核心模型
事件描述某次发生的交互,观察器描述某类状态的变化。正确设计先选信号,再界定传播范围、异步回调归属与清理,最后检查自己的写入会不会反过来制造同一信号。
原理与机制
事件路径是组件边界的一部分
事件通常沿捕获、目标、冒泡传播,但具体事件是否冒泡、能否取消需分别判断。事件委托在稳定祖先监听,从 target 找业务节点,并确认属于当前容器,不能把嵌套组件的按钮也纳入自己管理。currentTarget 表示当前监听器节点,stopPropagation 不等于 preventDefault,也不阻止同节点其他监听器。Shadow DOM 会重定向 target,跨边界还要看 composed;composedPath 只暴露调用方可见路径,闭合影子树不会因此变透明。
触控手势在开始前就有约定
passive 表达监听器不取消默认行为,让浏览器不必为滚动等待它;在被动监听中 preventDefault 无效。touch-action 预先声明浏览器允许的手势,如横向控件保留 pan-y 与缩放;开始后再改属性不会重新决定当前手势。Pointer Events 统一鼠标、笔和触控,pointer capture 保证指针移出后仍可接收相应事件,却不自动抢占滚动。状态按 pointerId 归属,并在 up、cancel、lostpointercapture 与卸载时完整清理。
观察器应匹配真正的问题
MutationObserver 观察 DOM 结构、属性与文本,不是尺寸或可见性 API;ResizeObserver 观察元素尺寸;IntersectionObserver 异步观察目标与根区域的相交。基础相交不等于人眼真正看见,遮挡、透明与注意力都不在简单判断里。观察回调不是同一执行阶段,不能混用 nextTick 或固定延时去猜。无限列表应选择正确滚动 root、合理 rootMargin 与阈值,同时保留按钮或分页以应对键盘和故障路径。
反馈必须收敛,加载必须前进
ResizeObserver 回调把宽度改成当前宽度加一会永远触发自己;放进 rAF 只是把循环延长到下一帧。优先让 CSS 决定布局,观察器更新独立的绘图缓冲,并只写真正改变的值。无限列表用 loading、hasMore、游标和查询版本防重;哨兵一直可见不会自动持续触发,因此每页布局完成后可串行检查是否需要补足。遇到空页、重复游标、错误或自动补足预算耗尽就停,避免把坏接口变成无限请求。
公共事件让封装保持稳定
影子树内部的业务事件若需要向祖先传播,通常显式设置 bubbles 与 composed,并用 detail 携带稳定记录 ID;cancelable 则另行决定调用方能否否决默认业务动作。从宿主自身派发时,应按实际传播路径判断所需标志,不能机械照抄。外部页面因此只依赖公开协议,内部从开放影子树改成封闭模式也不必修改父级选择器。验收一次操作只有一次通知,且阻止默认动作不会意外关闭无关的传播链。
最小示例
javascript点击按钮中的 span 仍能找到按钮,动态新增行也沿同一委托处理;嵌套的 data-list 则被所有权检查排除。原生 button 已处理键盘激活,不必再用 div 补一套。此示例针对普通 DOM,Shadow DOM 内部交互应发布稳定公共事件,不让父级依赖内部选择器。
环境:现代浏览器;页面已有 data-list 容器及带 data-id 的原生 button;这里只演示普通 DOM 委托。
核验:已静态审查示例与本章机制一致;未运行此示例,未进行框架或浏览器集成测试。观察结果为待复现的教学预期。
边界与取舍
边界
- 事件捕获与指针捕获是不同机制;后者不会自动阻止浏览器接管允许的滚动手势。
- rAF 不能修复不收敛的尺寸关系;observer 回调内的写入也可能制造新的观察记录。
- 哨兵持续相交不保证不断回调;通过反复 observe 强制刷新而无状态边界会造成请求风暴。
取舍
- 委托减少监听与动态绑定成本,但增加所有权判断;封装组件应优先明确事件接口。
- 提前预加载改善到达底部体验,却可能浪费流量;rootMargin 与自动补足预算应依据网络和内容密度测量。
口述示范
我先区分交互事件、尺寸变化、DOM 变化和相交状态,再选择对应 API。事件讲传播、默认行为与组件边界;观察器讲异步、收敛与清理。拖拽和无限列表的可靠性来自明确状态机,不能靠某个 API 名称自动获得。
章节练习
参考来源与核验边界
- MDN:Event.composedPath · 核验 2026-10-04
- MDN:Pointer events · 核验 2026-10-04
- MDN:ResizeObserver · 核验 2026-10-04
- MDN:Intersection Observer · 核验 2026-10-04
以现代 DOM、Pointer Events 与观察器 API 为基线;可见性增强选项、设备像素观察与 WebView 行为须单独检测。
内容版本:2026-10-04.2 · 题目和来源 ID 保持原样,本站不将面经标签解释为企业官方出题或高频保证。