变更事件与表单提交
change 与 input 的触发时机差在哪?
| 事件 | 何时触发 | 特点 |
|---|---|---|
change | 元素的值"改完了" | 文本输入要等失焦才触发 |
input | 值被用户每一次修改 | 立即触发, 不依赖键盘 |
- 文本输入: 打字过程中没有
change, 点到别处 (或按Tab) 时才触发一次; select、input type=checkbox/radio: 选择一变就立刻触发change;input覆盖面更广: 鼠标粘贴、语音识别输入都会触发, 因为只看"值变了没";input不触发的情况: 值没变动的按键, 例如方向键←→;- 想捕捉每一次修改, 选
input; 想在"输完"时处理, 选change; input里不能preventDefault(): 它在值已改完之后才触发, 阻止已经来不及;
input.oninput = () => (result.textContent = input.value);
cut/copy/paste 能拦下什么?
- 三者属于
ClipboardEvent, 携带event.clipboardData; - 可中止: 在处理器里
event.preventDefault()后, 剪切/复制/粘贴都不会发生;
input.onpaste = (event) => {
console.log(event.clipboardData.getData("text/plain"));
event.preventDefault(); // 本次粘贴作废
};
- 反直觉点: 在
cut/copy处理器里调用clipboardData.getData(...)拿到的是空串, 因为数据此刻还没进剪贴板; - 因此要读被选中文本, 用
document.getSelection(); clipboardData实现DataTransfer接口, 所以除了文本还能搬运文件等内容;- 异步替代:
navigator.clipboard可在任意上下文使用 (需要时向用户申请权限), Firefox 不支持;
剪贴板有哪些安全限制?
- 剪贴板是 OS 级全局资源, 页面不能随便读;
- 浏览器只在用户动作 (复制/粘贴等) 的处理程序内部放开访问;
dispatchEvent合成的剪贴板事件在多数浏览器被禁止, 即便发出也不给剪贴板数据;- 把
event.clipboardData存起来稍后再用同样无效, 它只在用户事件处理器的作用期内可用;
submit 事件何时触发, 怎么用它做校验?
- 两条提交途径:
| 途径 | 说明 |
|---|---|
点击 <input type="submit"> / type="image" | 常规提交按钮 |
在输入框里按 Enter | 无需点任何按钮 |
- 两者都会在
<form>上触发submit, 处理程序里校验数据, 有错就event.preventDefault()(onsubmit中写return false), 表单不再发往服务器; - 一个有趣细节: 在输入框按
Enter提交时,<input type="submit">上会触发click事件, 尽管用户并没有点击;
<form onsubmit="alert('submit!'); return false">
<input type="text" value="text" />
<input type="submit" value="Submit" />
</form>
form.submit() 和触发 submit 事件有什么区别?
form.submit(): 用 JS 直接提交;- 关键区别: 不会产生
submit事件, 也不执行校验 — 默认提交按钮走的是完整流程, 方法是"跳过流程, 直接发"; - 设计前提: 既然程序员主动调用, 就假定脚本已经做完相关处理;
- 用途: 动态造一个表单再发给服务器;
const form = document.createElement("form");
form.action = "https://google.com/search";
form.method = "GET";
form.innerHTML = '<input name="q" value="test">';
document.body.append(form); // 必须先入文档, 否则提交无效
form.submit();
- 需要保留校验与
submit事件的程序化提交, 用form.requestSubmit();
HTML 约束校验与 submit 如何分工?
- 声明式校验:
required、pattern等输入属性让浏览器先挡一道, 简单场景无需写 JS; - 程序化检查与反馈:
| 方法/属性 | 作用 |
|---|---|
form.checkValidity() | 校验并返回布尔值, 不打扰用户 |
form.reportValidity() | 校验并在不合规时弹出浏览器自带提示 |
input.validity | 逐项读取校验状态 (如 validity.valid) |
<form novalidate> | 关掉浏览器的自动校验, 完全交给自己处理 |
- 分工: 浏览器负责拦截与提示,
submit处理程序负责兜底与自定义逻辑; - 一致性问题:
form.submit()绕过校验, 所以"校验通过才发送"这类保证必须自己写;