onchange触发需同时满足值变化和元素失焦两个条件;select例外,选项切换即触发;文本类控件须失焦才触发;实时响应应使用oninput。
onchange 不是“值一变就执行”,它必须同时满足两个条件:值确实发生了变化,且元素已经 blur(失去焦点)。比如用户在 <input type="text"> 里输入“abc”再删成“ab”,最后点击页面空白处——这时才触发;如果一直没点别处、也没按 Tab,哪怕输了一百个字符,onchange 也不会执行。
因为 <select> 是特例:选项切换的瞬间就会触发 onchange,不需要等失焦。这是浏览器对表单控件的语义约定——选择动作本身即代表“确认”。但 <input type="text">、<textarea>、<input type="email"> 等文本类控件严格遵循“变值 + 失焦”双条件。
onchange 行为一致console.log(event.target.value) 配合 onblur 对比验证是否真失焦blur,某些 Android 浏览器会延迟触发,需额外监听 focusout
如果你要实现搜索建议、字数统计、密码强度提示这类功能,onchange 完全不合适——用户还没输完就关页,事件根本不会跑。应该换 oninput:
<input type="text" oninput="handleInput(this.value)">
oninput 在每次输入、粘贴、剪切、撤销后立即触发,无需失焦oninput 不会因 value 属性被 JS 修改而触发,只响应用户操作某些场景下,onchange 看似没反应,其实和初始值有关:
<input value="初始值">,用户输入相同内容(如也输“初始值”),即使失焦也不会触发 onchange——因为值未“改变”input.value = "新值" 后手动调用 input.dispatchEvent(new Event('change')) 才能模拟触发v-model 或受控组件会接管原生事件流,直接绑定 @change 仍走原生逻辑,但值同步时机可能掩盖失焦行为onchange 最适合用于“用户明确提交某一项”的时刻,比如修改邮箱后点别处、选完城市下拉框。把它当实时钩子用,八成会掉坑里。