JavaScript如何自动适配动态新增输入框的焦点记忆
解决方案
核心思路是无需提前维护input_X数组,在输入框获得焦点时实时计算它在所有.box-ipt元素中的位置,动态生成对应的标识字符串,这样不管HTML中新增多少个输入框,代码都能自动适配,无需手动修改。
修正后的存储焦点代码
window.addEventListener('load', () => { // 给所有.box-ipt绑定焦点事件 document.querySelectorAll('.box-ipt').forEach((input) => { input.onfocus = () => { // 获取当前input在所有.box-ipt中的索引(从0开始) const allInputs = document.querySelectorAll('.box-ipt'); const index = Array.prototype.indexOf.call(allInputs, input); // 生成input_X格式的标识并存入localStorage localStorage.setItem('myInputFocused_box1', `input_${index + 1}`); }; }); });
为什么之前的方案有问题?
- for循环方案:你提前在页面加载时生成了
values数组,但如果后续HTML中新增输入框,新的输入框不会被绑定焦点事件(因为querySelectorAll只在load时执行一次);另外,若页面重新加载时输入框数量变化,虽values会重新生成,但依赖提前生成的数组不如实时计算索引可靠,易因DOM顺序变动导致索引不匹配。 - 无限循环方案:这是典型死循环写法,
for(;;)会无限制执行,直接导致浏览器资源耗尽崩溃,完全不可行。
整合后的完整代码
将多个load事件监听合并,代码更简洁高效:
// 页面加载完成后执行所有初始化逻辑 window.addEventListener('load', () => { // 1. 从localStorage恢复上次的焦点 const baseanimdur = getComputedStyle(window.parent.document.documentElement).getPropertyValue('--base-anim-dur').replace('s', ''); const focusDelay = getComputedStyle(document.documentElement).getPropertyValue('--parent-grid-searchbox-focus-onload'); setTimeout(() => { const inputValue = localStorage.getItem("myInputFocused_box1") || ""; const inputNumber = inputValue.match(/\d+/)?.[0]; const allInputs = document.querySelectorAll(".box-ipt"); // 若有存储的编号则对应聚焦,否则聚焦第一个输入框 const input = inputNumber ? allInputs[inputNumber - 1] : allInputs[0]; input.focus(); }, baseanimdur / focusDelay); // 2. 绑定输入框焦点事件,实时存储当前焦点的标识 document.querySelectorAll('.box-ipt').forEach((input) => { input.onfocus = () => { const allInputs = document.querySelectorAll('.box-ipt'); const index = Array.prototype.indexOf.call(allInputs, input); localStorage.setItem('myInputFocused_box1', `input_${index + 1}`); }; }); // 3. 点击空白区域(body)时恢复焦点 const body = document.querySelector('body'); document.addEventListener('click', event => { // 原逻辑中条件判断两边执行相同操作,可简化 if (event.composedPath().includes(body)) { window.getActiveInputOnBTClick(); } }); }); // 点击搜索按钮时恢复焦点的函数 window.getActiveInputOnBTClick = () => { const inputValue = localStorage.getItem("myInputFocused_box1"); const inputNumber = inputValue?.match(/\d+/)?.[0]; const allInputs = document.querySelectorAll(".box-ipt"); const input = inputNumber ? allInputs[inputNumber - 1] : allInputs[0]; input.focus(); };
额外优化点
- 合并多个
window.addEventListener('load', ...),减少重复监听,提升代码执行效率。 - 在
getActiveInputOnBTClick函数中增加对localStorage.getItem结果的空值判断,避免因存储值不存在导致报错。 - 简化点击body的事件逻辑,原代码中条件判断的两个分支执行相同操作,明确只在点击body时执行聚焦逻辑(若需求是点击任何区域都聚焦,可直接去掉条件,直接调用
window.getActiveInputOnBTClick())。
内容的提问来源于stack exchange,提问作者Verminous
相关产品推荐
相关产品推荐

