input事件在每次输入变化时立即触发,change事件仅在失焦且值改变后触发;前者适用于实时校验与搜索,后者适合表单提交前验证。
监听用户输入,input 事件比 change 更及时:它在每次输入内容变化时触发(包括删除、粘贴、键盘输入),而 change 只在元素失去焦点且值发生改变后才触发。表单校验、实时搜索建议这类场景必须用 input,否则会漏掉中间状态。
input 事件不冒泡
change 冒泡,适合委托 和 上两者都可用;但 或 推荐用 change
change,但 input 在每次键入时已响应直接在 HTML 中写 oninput 属性最简,但推荐用 addEventListener——便于复用、解绑和避免内联脚本污染。
const inputEl = document.querySelector('#search');
inputEl.addEventListener('input', function (e) {
console.log('当前值:', e.target.value);
});
keyup 替代 input:无法捕获粘贴、拖入、语音输入等非键盘操作input,但 IE9 对 不触发,需降级用 propertychange
e.target.tagName === 'INPUT' 并过滤非文本类输入框用户每敲一个键就发请求或校验,会造成大量无效调用。必须加防抖,但不能简单套用通用函数——要确保最后一次输入后才执行,且首次输入不延迟。
function debounce(fn, delay) {
let timer;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
const debouncedSearch = debounce((value) => {
if (value.length > 1) fetch(`/api/search?q=${encodeURIComponent(value)}`);
}, 300);
inputEl.addEventListener('input', (e) => debouncedSearch(e.target.value));
e.target.value,因为闭包捕获的是触发时刻的值,应显式传参clearTimeout 后调用 cancelToken.cancel()
框架封装了底层事件,但机制不同:Vue 的 v-model 默认监听 input,React 的受控组件必须用 onChange(实际仍基于 input 事件)。
@input 覆盖 v-model,除非需要额外逻辑;想兼容 IE 可加 .lazy 修饰符切到 change
onChange 里直接 setState({ value: e.target.value }) 后再调用防抖——会导致 state 更新滞后;应先存原始值,再在防抖回调中读取e.target.value 可能包含未确认内容,可用 e.isComposing 过滤input 事件已把拼音“nihao”当真实输入发出去了。检测 e.isComposing === false 才执行业务逻辑,这一步几乎总被跳过。