DOM 事件、URL 与安全渲染:从点击处理到可靠导航
本文目录
早期 DOM 示例经常把事件处理、地址拼接和 HTML 字符串混在一个监听器中。现代交互应明确事件默认行为、目标元素、可信导航范围和内容输出上下文。
理解事件目标和默认行为
event.target 是实际触发事件的后代节点;event.currentTarget 是当前监听器绑定的位置。委托监听适合大量重复项:在稳定父节点上监听冒泡事件,再用 closest 找到操作按钮,并确认按钮确实属于这个列表,避免事件穿过嵌套组件后误命中。
preventDefault() 只应取消浏览器即将执行的默认动作,例如表单提交或链接导航;它不等于停止事件冒泡。stopPropagation() 会影响祖先监听器,通常不应作为修补组件边界的第一选择。键盘用户也必须可以完成操作:使用真实 button/a,不要只给任意 div 绑定点击。
const list = document.querySelector('[data-list]');
list.addEventListener('click', (event) => {
if (!(event.target instanceof Element)) return;
const button = event.target.closest('button[data-action]');
if (!button || !list.contains(button)) return;
const item = button.closest('[data-item]');
if (!item) return;
handleAction(button.dataset.action, item.dataset.id);
});
动态创建节点后通过事件委托减少监听器数量,但删除父节点时仍要清除订阅或由组件生命周期统一管理。不要在每次渲染时重复注册全局监听。
安全地生成链接
URL 参数应通过 URL / URLSearchParams 编码,不要手工拼接字符串。若地址来自用户输入、API 或文档,解析后仍要按业务 allowlist 检查协议和必要的主机;拦截 javascript: 等不允许协议。可信域名列表须经过规范化,不能只用字符串 includes 判断主机名。
function safeExternalUrl(raw) {
try {
const url = new URL(raw, window.location.origin);
if (!['https:', 'http:'].includes(url.protocol)) return null;
if (url.origin === window.location.origin) return url.href;
if (!['developer.mozilla.org', 'vuejs.org'].includes(url.hostname)) return null;
return url.href;
} catch {
return null;
}
}
const target = safeExternalUrl(input.value);
if (target) link.href = target;
生产环境通常只允许 HTTPS 外链;上例保留 HTTP 仅用于展示协议策略的选择点,实际部署应按业务收紧。新窗口打开外链时设置适当的 rel="noopener noreferrer" 并清楚标注外部跳转。回跳地址必须由服务器或受控的站内路由解析,不能让登录流程变成开放重定向。
文本与 HTML 是不同上下文
把用户文本作为文字显示时用 textContent 或框架的默认文本插值;不要用 innerHTML/insertAdjacentHTML 拼接不可信字符串。若确实需要富文本,必须使用经过维护的 HTML sanitizer,并以严格 allowlist 清除脚本、危险属性、URL 协议、SVG/MathML 等攻击面。CSP 是纵深防御,不会把不安全的 DOM sink 自动变安全。
显示带链接的普通文本时,可创建 DOM 节点并分别设置 textContent 与已校验的 href,不要依靠正则从任意文本中抽取后直接注入链接。事件数据、DOM dataset、查询参数都应视为不可信输入。
测试边界
构造空值、无效 URL、带用户名/端口/子域的钓鱼域名、协议相对 URL、内嵌标记文本、嵌套按钮和从列表外冒泡的事件。核验键盘焦点顺序、Enter/Space 行为、跳转告知、监听器清理和浏览器控制台。服务端仍需验证资源权限;隐藏链接不能充当访问控制。
参考:MDN Event target、MDN Event currentTarget、MDN URL API、MDN textContent、OWASP DOM based XSS Prevention、HTML Standard URL parsing。
Live Notes
留言提交后会先进入审核,审核通过后对其他读者公开。