给 2048 页面加键盘支持,踩了几个小坑

举报
yd_96310213 发表于 2026/10/26 08:11:06 2026/10/26
【摘要】 给 2048 小页面加键盘方向键支持的踩坑记录:preventDefault 的位置、switch 静默失败、gameover 状态检查,还有 key 和 code 的区别。

上周给之前那个 2048 的小页面加键盘方向键支持,本来以为十分钟的事,结果断断续续折腾了一个多小时。记录一下过程,主要给自己看。


起因很简单:同事在手机上玩我部署的那个 2048(就是活动里部署的那个静态页),说手机上只能滑,但我加触摸事件的时候把 touchstart 的默认行为没拦好,页面整体跟着滚。先把触摸的事修了,顺手想把键盘操作也补上,毕竟平时在电脑上调试用方向键更顺手。


键盘这边的第一版我是这么写的:document.addEventListener("keydown", (e) => { if (e.key === "ArrowUp") move("up"); ... }); 跑起来发现两个问题。一是按方向键页面会跟着滚动,因为 2048 的页面比视口高一点,方向键默认就有滚动行为。这个好办,e.preventDefault() 加上就行,但我一开始只在 move() 里面加,没拦住,后来才反应过来默认滚动发生在事件处理里,得在监听器里直接拦。


二是我不小心把 move("down") 写成了 move("down" )(多打了个空格),函数里 switch 匹配不到,静默失败,格子完全不动,也没有任何报错。排查的时候 console 里干干净净,我还以为监听器没挂上,绕了一圈。这个给我的教训是 switch 匹配不到最好加个 default 分支打个 log,至少失败的时候知道自己失败在哪。


后来又遇到一个更隐蔽的:游戏结束后有个「再来一局」按钮,鼠标点它没问题,但键盘 gameover 之后按方向键还会触发 move,会在一个已经结束的棋盘上继续合并,把分数算乱。原因是我的 move 函数没有检查游戏状态。加了一行 if (isGameOver) return; 才算完。


另外还有个小细节,e.key 在某些输入法开着的时候会返回 Process 而不是方向键名,我自己的测试机没复现,同事的机器上有过一次方向键失灵。后来改成了 e.code(ArrowUp 这些值在 e.code 里是固定的),目前没再听到他说有问题。key 和 code 的区别我之前一直没分太清,这次算是被迫搞明白了一半——为什么输入法会吞掉 key 事件的具体原因我还没查清楚,先记在这里。


最后的新键盘部分大概就三十行,核心就是:拦默认滚动、用 e.code、move 前查状态。改完让同事又试了一遍,他说手机上的滚动问题修好了,键盘那边他笔记本上玩着没再出问题。


遗留两个小困惑:一个是为什么 preventDefault 必须放在监听器顶层而不是 move 函数里才能拦住滚动,我猜和事件默认行为触发时机有关,但没找到特别确凿的文档说明;另一个就是上面说的输入法 Process 的具体机制。以后有空再翻翻 MDN。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。