推荐用 focusin/focusout 事件委托实现表单统一高亮:在 form 上监听 focusin 添加 .form-focused 类,focusout 延时判断 relatedtarget 是否离开表单再移除类,避免 tab 切换时闪动。

直接在表单控件上监听 focus 和 blur 是最直观的方式,但若想实现整张表单的统一高亮(比如聚焦任一输入框时,整个 <form></form> 加边框或阴影),推荐用事件委托 + focusin/focusout,它们支持冒泡,能精准控制“进入”和“真正离开”的时机。
给单个输入框加 focus/blur 样式反馈
适用于简单场景,如点击输入框变蓝、失焦后校验并标红:
- 用
addEventListener('focus', handler)添加获得焦点逻辑,例如添加.focused类、显示提示文案、清空错误状态 - 用
addEventListener('blur', handler)添加失去焦点逻辑,例如触发校验、保存临时值、隐藏提示 - 注意:
blur不冒泡,不能在父元素上靠它捕获子项失焦;如需委托,请改用focusout - CSS 中可配合
:focus伪类做基础样式,但 JS 控制更灵活(比如支持 contenteditable 或禁用态判断)
监听整个 form 实现高亮代理
避免为每个 input 单独绑定,提升可维护性,也适配动态增删字段:
- 在
<form></form>元素上监听focusin:只要任意可聚焦子元素(input、textarea、select、带contenteditable的元素)获得焦点,就给 form 添加.form-focused类 - 监听
focusout并延时判断是否“真离开”:获取event.relatedTarget,只有当它为null(点空白处、切窗口)或不在当前 form 内时,才移除高亮类 - 这样能防止 Tab 切换输入框时高亮频繁闪动,体验更稳定
关键细节与避坑提醒
实际开发中容易忽略但影响体验的点:
-
focus和blur默认不冒泡,委托必须用focusin/focusout - 禁用(
disabled)的表单控件不会触发焦点事件,无需额外过滤 - 自动聚焦推荐用 HTML 的
autofocus属性,而非 JS 调用.focus(),避免干扰页面加载流程 - 若需兼容旧版 Safari,注意
focusin/focusout在部分老内核中行为略有差异,可加简单降级逻辑
一个轻量可用的代码片段
不依赖框架,纯原生 JS:
const form = document.querySelector('form');
form.addEventListener('focusin', e => {
if (e.target.matches('input, textarea, select, [contenteditable]')) {
form.classList.add('form-focused');
}
});
form.addEventListener('focusout', e => {
setTimeout(() => {
const related = e.relatedTarget;
if (!related || !form.contains(related)) {
form.classList.remove('form-focused');
}
}, 0);
});











