Word Master游戏输入焦点跳转异常:第二行输入无自动切换
Word Master游戏焦点跳转问题解决方案
问题概述
开发Word Master类文字游戏,需求如下:
- 用户输入字母后,焦点自动跳转到同一行的下一个输入框
- 按Enter提交验证后,切换到下一行继续输入
当前第一行输入逻辑正常,但切换到第二行后,输入字母时(输入框长度myLength=1)焦点无法自动跳转。核心原因是原代码仅为初始row=0的.word元素绑定了onkeyup和onkeydown事件,切换行后未给新行绑定对应事件,导致焦点跳转逻辑失效。
解决方案
核心优化点
- 提取独立的事件处理函数:将原本绑定在初始行的
keyup和keydown逻辑抽成可复用函数,方便给任意行绑定 - 全局绑定事件:初始化时给所有
.word元素绑定事件,避免切换行后重复操作 - 修正焦点定位逻辑:切换行后,焦点应定位到当前行的第一个输入框,而非固定元素
- 优化状态变量重置:确保切换行时
counter、word等状态变量正确重置
修改后的完整代码
JavaScript代码
let counter = 1 let word = '' let fifthValue = '' let row = 0 // 工具函数:判断是否为字母 function isLetter(letter) { return /^[a-zA-Z]$/.test(letter) } // 通用keyup事件处理函数 function handleWordKeyup(event) { let target = event.srcElement || event.target let myLength = target.value.length // 记录输入的字母(counter<5时) if (isLetter(event.key) && counter < 5) { word += target.value } // 按Enter提交(counter=5时) if (event.key === 'Enter' && counter === 5) { fifthValue = target.value const wordArray = word.split('') wordArray[4] = fifthValue const newWord = wordArray.join('') // 验证单词 fetch('https://words.dev-apis.com/word-of-the-day?puzzle=1337') .then(response => response.json()) .then(data => { console.log(data) if (data.word === newWord) { console.log('你赢了!') } else { console.log('再试一次!') // 切换到下一行 row++ const currentRow = document.getElementsByClassName('word')[row] if (currentRow) { // 重置状态 counter = 1 word = '' fifthValue = '' // 聚焦当前行第一个输入框 currentRow.querySelector('input').focus() } } }) .catch(error => console.error(error)) } // 退格键清空当前输入框 if (event.key === 'Backspace') { target.value = '' } // 输入字母后跳转到下一个输入框 if (myLength === 1 && isLetter(event.key) && counter < 5) { let nextInput = target.nextElementSibling while (nextInput) { if (nextInput.tagName.toLowerCase() === 'input') { nextInput.focus() counter++ break } nextInput = nextInput.nextElementSibling } } console.log(counter, word) } // 通用keydown事件处理函数 function handleWordKeydown(event) { let target = event.srcElement || event.target let myLength = target.value.length // 禁止在第5个输入框输入超过1个字符 if (isLetter(event.key) && counter === 5) { target.value = target.value.slice(0, -1) event.preventDefault() } // 退格键跳转到上一个输入框 if (event.key === 'Backspace' && myLength === 0 && counter > 1) { let prevInput = target.previousElementSibling while (prevInput) { if (prevInput.tagName.toLowerCase() === 'input') { prevInput.focus() counter-- prevInput.value = '' word = word.slice(0, -1) break } prevInput = prevInput.previousElementSibling } } // 禁止输入非字母字符(退格、回车除外) if (!isLetter(event.key) && event.key !== 'Backspace' && event.key !== 'Enter') { event.preventDefault() } } // 初始化:给所有.word元素绑定事件 document.querySelectorAll('.word').forEach(wordRow => { wordRow.addEventListener('keyup', handleWordKeyup) wordRow.addEventListener('keydown', handleWordKeydown) }) // 初始聚焦第一行第一个输入框 document.querySelector('.word:first-child input').focus()
HTML代码(优化类名统一)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Word Master</title> <link rel="stylesheet" href="index.css" /> </head> <body class="page"> <h1 class="logo">Word Masters</h1> <div class="line"></div> <div class="nothing"></div> <div class="letter"> <div class="word"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> </div> <div class="word"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> </div> <div class="word"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> <input type="text" maxlength="1"> </div> <div class="word"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> </div> <div class="word"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> </div> <div class="word"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> <input maxlength="1"> </div> </div> <script src="./wordMaster.js"></script> </body> </html>
关键改进说明
- 事件复用:把
keyup和keydown逻辑抽成独立函数,初始化时给所有行绑定,避免切换行后重新绑定的麻烦 - 焦点修正:切换行后通过
currentRow.querySelector('input').focus()定位到当前行第一个输入框,不再依赖固定的.first类 - 输入限制优化:把非字母输入的限制整合到
keydown函数中,统一处理所有输入框的非法输入 - 状态变量管理:切换行时确保
counter、word等变量正确重置,避免跨行状态污染
内容的提问来源于stack exchange,提问作者Michał Francuz
相关产品推荐
相关产品推荐

