推荐用 addEventListener 替代 onfocus/onblur 内联属性,因其支持状态管理、条件逻辑、多输入框维护及框架集成;内联写法仅适用于无状态单输入框场景。
onfocus 和 onblur 属性可以配对使用,但直接写在 HTML 里容易失控——尤其是需要响应式状态、条件逻辑或多个输入框时,推荐用 addEventListener 替代。
比如单个输入框、无状态依赖、不涉及校验或样式联动时,可快速写成:
<input type="text" value="请输入邮箱" onfocus="this.value=''" onblur="if(!this.value) this.value='请输入邮箱'">
但这种写法很快会暴露问题:
Enter 提交或 Tab 切换时的焦点流转细节this.value 可能被框架劫持失效真正可控的做法是绑定事件监听器,并配合一个明确的状态变量(如 isFocused)或 class 控制行为:
input.addEventListener('focus', ...) 捕获聚焦,更新状态或样式input.addEventListener('blur', ...) 捕获失焦,触发校验或还原默认值focusout,因为 blur 不冒泡disabled)下不会触发任何焦点事件,无需额外判断示例中清空提示文本并避免重复恢复:
const input = document.querySelector('input');<br>let hasUserInput = false;<br><br>input.addEventListener('focus', () => {<br> if (input.value === '请输入邮箱') {<br> input.value = '';<br> input.classList.add('active');<br> }<br>});<br><br>input.addEventListener('blur', () => {<br> if (!input.value && !hasUserInput) {<br> input.value = '请输入邮箱';<br> input.classList.remove('active');<br> }<br>});<br><br>input.addEventListener('input', () => {<br> hasUserInput = true;<br>});
失焦不是“鼠标点开别处”才发生,它可能在以下情况触发:
Tab 移出当前输入框(包括循环到第一个元素)button、a[href]、其他 input)element.blur() 或切换浏览器标签页(部分浏览器)document.body 点击触发——因为 body 默认不可聚焦,除非加了 tabindex
所以别假设 blur 一定代表“用户完成填写”,它只是“离开当前控件”。真正判断是否提交,应以 submit 或显式按钮点击为准。
页面加载时想默认聚焦,优先用 HTML 的 autofocus 属性:
<input type="text" autofocus>
而不是在 DOMContentLoaded 里调用 input.focus(),原因有三:
autofocus 由浏览器统一管控,兼容屏幕阅读器,且不会打断用户正在做的操作input.focus() 在某些移动端或 iframe 场景下会被静默拒绝,无报错也无效果autofocus,JS 中的初始 isFocused 状态也得设为 true,否则状态与 DOM 不一致复杂交互里,焦点状态容易和表单校验、无障碍属性(aria-invalid)、CSS 伪类(:focus-within)产生耦合,动一个得核对一整条链。先理清“谁该决定焦点何时生效”,再写代码。