不能利用事件捕获阶段做全局权限预校验,因其仅适用于原生DOM事件流,无法拦截fetch、localStorage等非事件操作;真正可行的是HTTP请求层拦截、敏感API封装和路由级前置控制三类方案。

不能利用事件捕获阶段(useCapture = true)做全局权限预校验。
原因很直接:事件捕获只适用于原生 DOM 事件流(如 click、keydown、submit),而权限校验真正要拦的,往往根本不在这个流里。
比如你希望在用户点击“导出报表”按钮前检查是否有 export:pdf 权限——按钮点击本身确实能被捕获监听;但若用户绕过按钮,直接调用 window.fetch('/api/export') 或执行 localStorage.setItem('token', 'xxx'),这些操作不触发任何 DOM 事件,addEventListener('click', handler, true) 完全无感。
所以,靠 capture 阶段做“全局”预校验,实际覆盖范围非常有限,容易造成严重误判。
真正可行的权限预校验入口有三类,按适用场景分:
-
HTTP 请求层拦截
劫持window.fetch和XMLHttpRequest.prototype.send,在请求发出前检查 URL、method、headers 或 body 内容是否匹配当前用户权限。
示例:const originalFetch = window.fetch; window.fetch = function(...args) { const [url] = args; if (url.includes('/api/admin/') && !hasPermission('admin:access')) { throw new Error('Insufficient permission'); } return originalFetch.apply(this, args); }; 存储与剪贴板等敏感 API 封装
用Proxy包裹localStorage.setItem,或重写navigator.clipboard.writeText,加入同步权限判断。
注意:Clipboard.writeText必须在用户手势上下文中调用,且无法异步阻塞,校验需即时完成。路由/导航级前置控制(前端单页应用)
Vue Router 的router.beforeEach、React Router 的useNavigate拦截、或 Angular 的CanActivate守卫,适合在页面跳转前校验角色或权限码。
这类守卫不依赖 DOM 事件流,而是介入框架自身的导航生命周期。
额外提醒:
- 单纯监听
click并在捕获阶段stopPropagation()或preventDefault(),只能拦住显式点击,拦不住键盘回车、脚本调用、快捷键、自动提交等路径; - 所有 JS 层拦截都可被开发者工具绕过,生产环境关键权限必须后端二次校验;
- 若需拦截更底层行为(如截图、下载、iframe 跳转),浏览器扩展是目前唯一可靠方案,但需用户授权且脱离页面 JS 上下文。
本质上,权限预校验不是“监听什么”,而是“替换什么”——把原始敏感行为替换成带校验逻辑的包装函数。

















