onfocus和onblur配对使用: 焦点状态切换技巧

作者:技术拾光

时间:2026-06-17

浏览:532

就拿焦点状态来说吧,这问题看着不大,但真正踩过坑的人都清楚,一旦涉及的输入框变多,或者逻辑变得复杂起来,内联写法中那堆 onfocus 和 onblur 简直就是埋雷。说实话,真正能撑住场面的,还得是 addEventListener。 onfocus 和 onblur 这两个属性确实可以配对使用,

文章目录

就拿焦点状态来说吧,这问题看着不大,但真正踩过坑的人都清楚,一旦涉及的输入框变多,或者逻辑变得复杂起来,内联写法中那堆 onfocus 和 onblur 简直就是埋雷。说实话,真正能撑住场面的,还得是 addEventListener。

onfocus和onblur配对使用: 焦点状态切换技巧

onfocus 和 onblur 这两个属性确实可以配对使用,但问题在于直接写死在 HTML 里很容易失控。一旦涉及响应式状态、条件逻辑,或者需要处理多个输入框,addEventListener 才是更稳妥的选择。

onfocus/onblur 属性只适合最简场景

什么叫最简场景?比如只有一个输入框,没有状态依赖,不涉及校验,也不需要样式联动。那你可以快速写成这样:

但这种写法很快就会暴露问题:

  • 你根本分不清用户是“清空后失焦”,还是“从未输入就离开”,结果提示文案动不动就误恢复。
  • 想监听 Enter 提交或者 Tab 切换时的焦点流转细节?没门。
  • 多个输入框共用同一段内联脚本,维护成本直线上升,出错了都找不到源头。
  • 跟 React、Vue 这类框架的状态同步更是麻烦,this.value 很可能被框架劫持,直接失效。

用 addEventListener 实现可维护的焦点状态切换

真正可控的做法是绑定事件监听器,同时配合一个明确的状态变量(比如 isFocused)或者 class 来控制行为。这样做的好处是逻辑清晰,好维护。

  • 用 input.addEventListener('focus', ...) 捕获聚焦,更新状态或样式。
  • 用 input.addEventListener('blur', ...) 捕获失焦,触发校验或还原默认值。
  • 有个细节要留心:如果你想监听子元素失焦的委托(比如表单容器统一处理),必须用 focusout,因为 blur 不冒泡。
  • 禁用状态下的输入框压根不会触发任何焦点事件,省了你再写 if 判断的功夫。

下面这个例子展示的是如何清空提示文本,并避免重复恢复:

const input = document.querySelector('input');
let hasUserInput = false;

input.addEventListener('focus', () => {
if (input.value === '请输入邮箱') {
input.value = '';
input.classList.add('active');
}
});

input.addEventListener('blur', () => {
if (!input.value && !hasUserInput) {
input.value = '请输入邮箱';
input.classList.remove('active');
}
});

input.addEventListener('input', () => {
hasUserInput = true;
});

blur 时机比你想的更微妙

失焦这件事可没那么简单,它不只是“鼠标点开别处”才会发生。以下这些情况都会触发 blur:

  • 按 Tab 移出当前输入框(哪怕循环到第一个元素也算)。
  • 点击页面上其他可聚焦的元素,比如 button、a[href]、其他 input。
  • 调用 element.blur(),或者切换浏览器标签页(部分浏览器会触发)。
  • 但注意,在 document.body 上点击不会触发——因为 body 默认不可聚焦,除非你给它加了 tabindex。

所以,别想当然地认为 blur 一定代表“用户完成了填写”,它只是“离开了当前控件”。真正要判断是否提交,还是得以 submit 事件或者显式的按钮点击为准。

autofocus 不等于 JS focus(),别混用

页面加载时想默认聚焦,优先用 HTML 的 autofocus 属性:

而不是在 DOMContentLoaded 里调用 input.focus()。原因有三:

  • autofocus 由浏览器统一管控,兼容屏幕阅读器,还不会打断用户当前正在进行的操作。
  • input.focus() 在某些移动端或 iframe 场景下会被静默拒绝,既没报错也没效果,容易让人摸不着头脑。
  • 如果已经用了 autofocus,JS 里初始的 isFocused 状态也得设为 true,否则状态跟 DOM 就对不上了。

在复杂交互里,焦点状态很容易跟表单校验、无障碍属性(比如 aria-invalid)、CSS 伪类(:focus-within)耦合在一起。动一个地方,就得把整条链都核对一遍。这里想补充一句:先理清“谁该决定焦点何时生效”,再动手写代码,能省下不少麻烦。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›