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 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 不支援

安全限制

剪貼簿是作業系統層級的「全域」事物。使用者可能會在各種應用程式之間切換、複製/貼上不同的東西,而瀏覽器頁面不應該看到所有這些。

因此,大多數瀏覽器只允許在特定使用者動作(例如複製/貼上等)的範圍內無縫讀取/寫入剪貼簿。

禁止在所有瀏覽器中使用 dispatchEvent 產生「自訂」剪貼簿事件,唯 Firefox 例外。即使我們設法發送此類事件,規範也明確指出此類「合成」事件不得提供對剪貼簿的存取權。

即使有人決定在事件處理常式中儲存 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…)