2022 年 10 月 4 日

事件:change、input、cut、copy、paste

让我们介绍一下伴随数据更新的各种事件。

事件:change

当元素完成更改时,会触发change事件。

对于文本输入,这意味着当它失去焦点时会发生事件。

例如,当我们在下面的文本字段中键入时——没有事件。但是,当我们将焦点移到其他地方时,例如,单击按钮——将会有一个change事件

<input type="text" onchange="alert(this.value)">
<input type="button" value="Button">

对于其他元素:selectinput type=checkbox/radio,它会在选择更改后立即触发

<select onchange="alert(this.value)">
  <option value="">Select something</option>
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
  <option value="3">Option 3</option>
</select>

事件:input

input 事件在用户修改值后每次都会触发。

与键盘事件不同,它会在任何值更改时触发,即使不涉及键盘操作:使用鼠标粘贴或使用语音识别来听写文本。

例如

<input type="text" id="input"> oninput: <span id="result"></span>
<script>
  input.oninput = function() {
    result.innerHTML = input.value;
  };
</script>

如果我们希望处理 <input> 的每次修改,那么此事件是最佳选择。

另一方面,input 事件不会在键盘输入和其他不涉及值更改的操作中触发,例如在输入时按箭头键

无法在 oninput 中阻止任何操作

input 事件在值修改后发生。

因此,我们无法在那里使用 event.preventDefault() - 这太迟了,不会有任何效果。

事件:剪切、复制、粘贴

这些事件在剪切/复制/粘贴值时发生。

它们属于 ClipboardEvent 类,并提供对剪切/复制/粘贴的数据的访问。

我们还可以使用 event.preventDefault() 来中止操作,然后什么都不会被复制/粘贴。

例如,以下代码阻止所有 cut/copy/paste 事件,并显示我们尝试剪切/复制/粘贴的文本

<input type="text" id="input">
<script>
  input.onpaste = function(event) {
    alert("paste: " + event.clipboardData.getData('text/plain'));
    event.preventDefault();
  };

  input.oncut = input.oncopy = function(event) {
    alert(event.type + '-' + document.getSelection());
    event.preventDefault();
  };
</script>

请注意:在 cutcopy 事件处理程序中,对 event.clipboardData.getData(...) 的调用会返回一个空字符串。这是因为从技术上讲,数据尚未在剪贴板中。如果我们使用 event.preventDefault(),它将根本不会被复制。

因此,上面的示例使用 document.getSelection() 来获取选定的文本。你可以在文章 选择和范围 中找到有关文档选择的更多详细信息。

不仅可以复制/粘贴文本,还可以复制/粘贴所有内容。例如,我们可以在操作系统文件管理器中复制一个文件,然后将其粘贴。

这是因为 clipboardData 实现了 DataTransfer 接口,该接口通常用于拖放和复制/粘贴。这有点超出了我们的范围,但你可以在 DataTransfer 规范 中找到它的方法。

此外,还有一个额外的异步 API 来访问剪贴板:navigator.clipboard。有关它的更多信息,请参阅规范 剪贴板 API 和事件Firefox 不支持

安全限制

剪贴板是“全局”操作系统级的东西。用户可以在各种应用程序之间切换,复制/粘贴不同的内容,并且浏览器页面不应该看到所有这些。

因此,大多数浏览器只允许在某些用户操作(例如复制/粘贴等)的范围内无缝读写访问剪贴板。

除了 Firefox 之外,所有浏览器中都禁止使用 dispatchEvent 生成“自定义”剪贴板事件。即使我们设法分派这样的事件,规范也明确指出,此类“合成”事件不得提供对剪贴板的访问。

即使有人决定在事件处理程序中保存 event.clipboardData,然后稍后访问它——它也不会起作用。

重申一下,event.clipboardData 仅在用户启动的事件处理程序上下文中工作。

另一方面,navigator.clipboard 是较新的 API,旨在在任何上下文中使用。它会根据需要请求用户权限。

摘要

数据更改事件

事件 描述 特殊功能
change 值已更改。 对于文本输入,在失去焦点时触发。
input 对于文本输入,每次更改时触发。 change 不同,立即触发。
cut/copy/paste 剪切/复制/粘贴操作。 可以防止操作。event.clipboardData 属性允许访问剪贴板。除 Firefox 之外的所有浏览器还支持 navigator.clipboard

任务

重要性:5

创建一个界面,允许输入银行存款金额和百分比,然后计算一段时间后金额是多少。

以下是演示

应立即处理任何输入更改。

公式为

// initial: the initial money sum
// interest: e.g. 0.05 means 5% per year
// years: how many years to wait
let result = Math.round(initial * (1 + interest) ** years);

为任务打开沙箱。

教程地图

评论

在评论之前阅读此内容…
  • 如果您有改进建议,请 提交 GitHub 问题 或提交拉取请求,而不是发表评论。
  • 如果您无法理解文章中的某些内容,请详细说明。
  • 要插入几行代码,请使用 <code> 标记,对于多行代码,请将其包装在 <pre> 标记中,对于 10 行以上的代码,请使用沙箱 (plnkrjsbincodepen…)