☰
浏览器按键失灵踩坑记录
2026/10/1 15:57:57 网站建设 项目流程

浏览器按键失灵踩坑记录

一、按键失灵

文章目录

  • 浏览器按键失灵踩坑记录
    • 一、按键失灵
      • 1.1 按现象对原因
      • 1.2 外部抢键
      • 1.3 三步定位
      • 1.4 处理
    • 二、在被节流的页面里验证动画
    • 三、其它
      • 3.1 对象方法之间不能按名字互相调用
      • 3.2 ES 模块缓存导致新旧代码混跑
      • 3.3 `.gitignore` 否定规则
      • 3.4 着色器通道与阈值方向
      • 3.5 压缩按下游用途分层
      • 3.6 交互参数先量化
    • 四、验证信号

1.1 按现象对原因

现象原因确认方式
所有键都无效焦点不在能接收键的元素上看document.activeElement;鼠标点一下目标区域再试
某个字母键无效,同页别的字母键正常外部程序抢键(扩展 / 宿主 / 输入法 / 系统工具)见 1.3
某个组合键无效撞上浏览器或系统保留键换组合(Ctrl+0/Ctrl+S会被浏览器拿走)
等价按钮有效,只有键无效与业务逻辑无关,问题在"键"这一层这条本身就是分界线
开发者侧正常,用户侧无效环境差异(扩展、宿主、输入法、键盘布局)让用户回传 1.4 的探针结果
只在某些时候无效焦点被输入框/弹窗抢走;<dialog>打开时页面收不到键是否刚点过输入框、是否有 modal 开着
e.key值异常输入法合成中(isComposing/key: 'Process')、非 QWERTY 布局打印e.key与e.isComposing

1.2 外部抢键

同一份代码,有的键灵、有的键不灵,按钮好使。keydown 在页面之前就被扩展或宿主消费掉了,
addEventListener('keydown')不触发,处理器里加日志也看不到。

来源典型被占的键特征
视频倍速类扩展(Video Speed Controller / Global Speed)AD(减速/加速)、R(重置倍速),部分还有SZX按下后页面角落浮出当前倍率数字(如1.6),默认一档 0.1
Vimium / 键盘导航类扩展几乎全部字母有提示条或光标跳转
翻译 / 截图 / 笔记 / 密码管理类扩展常占TSECtrl+Shift+*有浮层或侧栏弹出
IDE 内置浏览器、Electron / CEF 外壳宿主自己绑定的全局键禁用扩展仍复现
输入法字母键报key: 'Process'或isComposing: true切英文输入法正常
截图 / 录屏 / 显卡驱动 / 游戏辅助不固定换浏览器、换机器仍复现

辨认"数字浮层":

  • 细步进倍率(1.0→1.1→…→1.6)是视频倍速扩展的特征,浏览器缩放不会出现1.6这种值。
  • 该浮层不在页面 DOM 里(querySelectorAll('body *')找不到)。扩展常用 closed shadow root,
    querySelector看不到属于正常现象。
  • 确认途径:鼠标悬停看 tooltip,或「扩展管理 → 该扩展 → 快捷键」查是否绑了这个键。

本项目实例:用户报"按 R 复位无效",F 与空格正常,复位按钮有效。把同一功能改绑到C后有效,
说明代码路径无差异;r/R的绑定从首个提交起未变过。真因是用户装了视频倍速扩展,R是它的
“重置倍速”,A/D是"减速/加速"(用户按 A/D 时看到浮出1.6)。

定位过程中的无效改动:把复位语义从"开自动摆动"改成"停住"、加C别名、再换成D——都没触及
原因。期间用截图和像素差异做验证,得出过三次互相矛盾的结论(原因见第二节)。

1.3 三步定位

  1. 找等价按钮。按钮有效 → 业务逻辑没问题,问题在键这一层,直接排除"函数写错了"整类原因。

  2. 换一个键试。功能改绑另一个字母后有效 → 基本断定外部抢键(代码路径完全相同);仍无效 →
    回到 1.1 的"所有键都无效",查焦点。

  3. 上探针,看页面实际收到了什么。写到 DOM 而不是console.log(用户不一定开控制台):

    el.addEventListener('keydown',(e)=>{el.dataset.lastkey=e.key;el.dataset.lastComposing=e.isComposing;// 只在"认得的键"上 preventDefault});

    控制台读document.querySelector('...').dataset.lastkey:

    • 停在上一个成功的键 → 目标键没到页面,外部抢键
    • 显示目标键 → 键到了页面,问题在后续逻辑
    • 一直undefined→ 键盘事件没进页面(焦点或宿主层面)

    ev.defaultPrevented也可以作为"是否被接受"的信号,一个合成事件就能验证绑定,
    不依赖页面可见性和渲染循环(见第四节)。

1.4 处理

  • 治本:让用户在「扩展快捷键」里解绑冲突键,或本项目改用不冲突的键。页面侧无法绕过。
  • 兜底:重要操作永远保留一条指针路径——按钮、双击、长按。键盘作为附加入口,不作为唯一入口。
  • 不把r/R/c/C/d/D全绑上。别名会掩盖真因,定位清楚后留一个正式键,冲突写进注释。

二、在被节流的页面里验证动画

自动化 / 无头 / 后台标签页里document.hidden会翻转,而渲染循环通常写成:

functionframe(now){if(!document.hidden&&visible)step(now);elselastTime=now;raf=requestAnimationFrame(frame);}

step()被跳过时,两类实现的行为不同:

行为实现方式隐藏时
拖拽 / 直接赋值直接写最终状态(obj.rotation = ...)照常生效
补间 / 复位 / 翻转只改target,靠step()里的缓动收敛完全无变化

结果是"隐藏时拖拽能动、复位不动"被读成"复位坏了"。用同一个方法测已知能用的翻转也测不出来,
说明量具本身失效,此时任何基于画面的结论都不可信。

对策:

  • 验证前确认document.hidden、visible、rAF 是否在跑。
  • 改用不依赖渲染循环的信号(见第四节)。
  • 动画的观感和手感只能真人验证;自动化只能验逻辑。

三、其它

3.1 对象方法之间不能按名字互相调用

constapi={flip(v){/* ... */},reset(){flip(false);},// ReferenceError: flip is not defined};

flip是对象属性,不是作用域里的名字,方法内部裸名引用不到。node --check查不出来——
语法合法,失败发生在运行时名字解析。

抽成闭包函数,两个方法都调它:

functionsetFace(v){/* ... */}constapi={flip(v=!flipped){setFace(v);},reset(){setFace(false);}};

"改完没语法错、一调用就炸"的先查名字解析:打错字、作用域外引用、被同名变量遮蔽。只有实跑能发现。

3.2 ES 模块缓存导致新旧代码混跑

index.html/main.js是新的,被import的子模块还是旧的。症状表现为"提示文案写着新键位,
按下去没反应"这类自相矛盾的现象。

  • 构建号写进 DOM,比看 Network 面板快:
    container.dataset.build="2026-09-30.7";// 控制台:document.querySelector('#app').dataset.build
  • 改了行为就递增号位,否则标记无意义。
  • Cache-Control: no-store不保证 ES 模块不缓存,需要强刷(Ctrl+Shift+R)。
  • 排错先问"这个页面是什么时候加载的"。

3.3.gitignore否定规则

  1. 最后匹配生效:!important-file.png必须放在*.png之后,放前面等于没写。
  2. 父目录被整体排除时,目录内文件无法再否定(!dir/file无效)。

否定规则统一放文件末尾并注释说明顺序不能动。用git check-ignore -q <path> && echo 仍被忽略
验证,不靠肉眼看。

3.4 着色器通道与阈值方向

线稿辉光一直不亮。着色器是

line = (1. - smoothstep(.06, .25, texture2D(tLine, uv).r))

只读红色通道,且越暗越亮。生成脚本把阈值图写进 alpha、RGB 留全白,红通道恒为 1,辉光恒为 0。

  • 先找采样语句,确认读哪个通道、阈值区间、方向(smoothstep还是1 - smoothstep)。
  • 需要过渡就把强度直接当遮罩(保留中灰过渡带)。p > 阈值 ? 0 : 255硬切会扔掉阈值区间内的柔和段。
  • 轮廓单独从 alpha 取:深色主体贴透明区时 RGB 落差太小,边缘检测抓不到。

3.5 压缩按下游用途分层

用途选择原因
平滑渐变 / 照片有损(WebP q88~90)肉眼无差,体积降 5~20 倍
参与阈值判断的图(mask / 描边 / 深度)无损有损会把数值糊过阈值区间产生斑块;分辨率可降到一半——按归一化 UV 采样,与分辨率无关
平色 + 柔和 alpha无损有损在边缘产生色晕

3.6 交互参数先量化

“拖拽手感差、旋转不顺手”,凭感觉改容易越改越玄。先量出可指认的数字:

  • 灵敏度0.006 rad/px× 限位±0.65 rad→ 拖 108px 撞墙,之后是死区(实测拖 250px 只转 44°,
    后半段效率降到 1/6)。
  • 渲染按时间常数8/s追目标 → 每帧落后0.03~0.07 rad。

据此改成软限位 + 直接写实际值,改完用同样两个数字验收。数值合理不等于体验好,最终仍需真人确认。


四、验证信号

按可信度与成本排序:

手段用来验说明
ev.defaultPrevented事件绑定是否生效处理器只对接受的输入调preventDefault();合成事件即可判定,不需要页面可见、不需要渲染循环
DOM 属性信号状态变更aria-pressed/dataset.*同步可读,比截图像素可靠
两条路径对照分层定位按钮 vs 键盘、旧键 vs 新键,差异本身即证据
亮区重心 / 面积姿态、正反面对流光等高频噪声不敏感;整幅平均亮度通常只能区分明显不同的两态
跨调用分段读被节流的动画状态挂window,借两次执行之间的墙钟时间让节流的帧跑完
假外部服务网络链路假 SMTP / mock API 可反复跑,真实服务会限流
真人操作手感 / 视觉不可替代

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询