JavaScript 複習之各類事件(二)

DreamTruth發表於2019-03-03

表單事件

一、事件種類

input事件

<input><select><textarea>的值發生變化時觸發。

input事件的一個特點,就是會連續觸發,比如使用者每按下一次按鍵,就會觸發一次input事件。

select事件

當在<input><textarea>裡面選中文字時觸發。

change事件

<input><select><textarea>的值發生變化時觸發。

invalid事件

使用者提交表單時,如果表單元素的值不滿足校驗條件,就會觸發invalid事件。

<form>
  <input type="text" required oninvalid="console.log('invalid input')" />
  <button type="submit">提交</button>
</form>
複製程式碼

上面程式碼中,輸入框是必填的。如果不填,使用者點選按鈕提交時,就會觸發輸入框的invalid事件,導致提交被取消。

reset 事件 submit 事件

reset事件當表單重置(所有表單成員變回預設值)時觸發。

submit事件當表單資料向伺服器提交時觸發。注意,submit事件的發生物件是<form>元素,而不是<button>元素,因為提交的是表單,而不是按鈕。

二、 InputEvent 介面

  • InputEvent.data返回一個字串,表示變動的內容。
  • InputEvent.inoutType返回一個字串,表示字串發生變更的型別
  • InputEvent.dataTransfer返回一個 DataTransfer 例項。該屬性只在文字框接受貼上內容(insertFromPaste)或拖拽內容(insertFromDrop)時才有效。

觸控事件

瀏覽器的觸控API由三部分組成:

  • Touch:一個觸點
  • TouchList:多個觸控點的集合
  • ToucheEvent:觸控引發的事件例項

Touch 介面

例項屬性

  • Touch.identifier返回一個整數,表示觸控點的位移ID。這個值在整個觸控過程保持不變,直到觸控事件結束。

  • Touch.screenX屬性和Touch.screenY屬性,分別表示觸控點相對於螢幕左上角的橫座標和縱座標,與頁面是否滾動無關。

  • Touch.clientX屬性和Touch.clientY屬性,分別表示觸控點相對於瀏覽器視口左上角的橫座標和縱座標,與頁面是否滾動無關。

  • Touch.pageX屬性和Touch.pageY屬性,分別表示觸控點相對於當前頁面左上角的橫座標和縱座標,包含了頁面滾動帶來的位移。

  • Touch.radiusX屬性和Touch.radiusY屬性,分別返回觸控點周圍受到影響的橢圓範圍的 X 軸半徑和 Y 軸半徑,單位為畫素。乘以 2 就可以得到觸控範圍的寬度和高度。

  • Touch.rotationAngle屬性表示觸控區域的橢圓的旋轉角度,單位為度數,在090度之間。

  • Touch.force屬性返回一個0到1之間的數值,表示觸控壓力。0代表沒有壓力,1代表硬體所能識別的最大壓力。

  • Touch.target返回一個元素節點,代表觸控發生時所在的那個元素節點。

TouchList介面

表示一組觸控點的集合,他們的例項是一個類陣列物件。使用者用三根手指觸控,產生的TouchList例項就會包含三個成員,每根手指的觸控點對應一個Touch例項物件。

例項主要通過觸控事件的TouchEvent.touchesTouchEvent.changedTouchesTouchEvent.targetTouches這幾個屬性獲取。

觸控事件種類

  • touchstart:使用者開始觸控時觸發
  • tauchend:使用者不再接觸觸控式螢幕時觸發
  • touchmove:使用者移動觸控點時觸發
  • touchcancel:觸控點取消時觸發,比如在觸控區域跳出一個模態視窗(modal window)、觸控點離開了文件區域(進入瀏覽器選單欄)、使用者的觸控點太多,超過了支援的上限(自動取消早先的觸控點)。

拖拉事件

一、事件種類

  • drag:拖拉過程中,在被拖拉的節點上持續觸發
  • dragStart:開始拖拉時,在被拖拉的節點上觸發
  • dragend:拖拉結束時觸發
  • dragenter:拖拉進入當前節點時,在當前節點上觸發一次。
  • dragover:脫拉到當前節點上方時,在當前節點上持續觸發
  • dragleave:拖拉操作離開當前節點範圍時,在當前節點上觸發
  • drop:被拖拉的節點或被選中的文字,釋放到目標節點時,在目標節點上觸發
/* HTML 程式碼如下
 <div class="dropzone">
   <div id="draggable" draggable="true">
     該節點可拖拉
   </div>
 </div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
*/

// 被拖拉節點
var dragged;

document.addEventListener('dragstart', function (event) {
  // 儲存被拖拉節點
  dragged = event.target;
  // 被拖拉節點的背景色變透明
  event.target.style.opacity = 0.5;
}, false);

document.addEventListener('dragend', function (event) {
  // 被拖拉節點的背景色恢復正常
  event.target.style.opacity = '';
}, false);

document.addEventListener('dragover', function (event) {
  // 防止拖拉效果被重置,允許被拖拉的節點放入目標節點
  event.preventDefault();
}, false);

document.addEventListener('dragenter', function (event) {
  // 目標節點的背景色變紫色
  // 由於該事件會冒泡,所以要過濾節點
  if (event.target.className === 'dropzone') {
    event.target.style.background = 'purple';
  }
}, false);

document.addEventListener('dragleave', function( event ) {
  // 目標節點的背景色恢復原樣
  if (event.target.className === 'dropzone') {
    event.target.style.background = '';
  }
}, false);

document.addEventListener('drop', function( event ) {
  // 防止事件預設行為(比如某些元素節點上可以開啟連結),
  event.preventDefault();
  if (event.target.className === 'dropzone') {
    // 恢復目標節點背景色
    event.target.style.background = '';
    // 將被拖拉節點插入目標節點
    dragged.parentNode.removeChild(dragged);
    event.target.appendChild( dragged );
  }
}, false);
複製程式碼

關於拖拉事件,注意以下幾點:

  • 拖拉過程只觸發以上這些事件,儘管滑鼠在移動,但是滑鼠事件不會觸發
  • 將檔案從作業系統拉進瀏覽器,不會觸發dragstartdragend事件
  • dragenterdragover事件的監聽函式,用來取出拖拉資料。由於網頁的大部分割槽域不適合作為放下拖拉元素的目標幾點,所以這兩個事件的預設設定為當前節點不允許接受被拖拉的元素,如果想要在目標節點上放下的資料,首先必須阻止這兩個事件的預設行為。

二、DataTransfer 介面

所有的拖拉事件的例項都一個DragEvent.dataTransfer屬性,用來讀寫需要傳遞的資料

三、DataTransfer的例項屬性

DataTransfer.dropEffect

用來設定放下(drop)被拖動節點時的效果,會影響到拖拉經過相關區域時滑鼠的形狀。可取下面的值:

  • copy:複製被拖動的節點

  • move:移動被拖拉的節點

  • link:建立指向被拖拉的節點的連結

  • none:無法放下被拖拉的節點

dropEffect屬性一般在dragenterdragover事件的監聽函式中設定,對於dragstartdragdragleave這三個事件,該屬性不起作用。

DataTransfer.effectAllowed

屬性設定本次拖拉中允許的效果,可能的取值:

  • copy:複製被拖拉的節點
  • move:移動被拖拉的節點
  • link:建立指向被拖拉節點的連結
  • copyLink:允許copy或link
  • copyMove:允許copy或move
  • linkMove:允許link或move
  • all:允許所有效果
  • none:無法放下被拖拉的節點
  • uninitialized:預設值,等同於all

如果某種效果是不允許的,使用者就無法在目標節點中達成這種效果。

dragstart事件的監聽函式,可以用來設定這個屬性。其他事件的監聽函式裡面設定這個屬性是無效的。

DataTransfer.files

屬性是一個 FileList 物件,包含一組本地檔案,可以用來在拖拉操作中傳送。如果本次拖拉不涉及檔案,則該屬性為空的 FileList 物件。

// HTML 程式碼如下
// <div id="output" style="min-height: 200px;border: 1px solid black;">
//   檔案拖拉到這裡
// </div>

var div = document.getElementById('output');

div.addEventListener("dragenter", function( event ) {
  div.textContent = '';
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("dragover", function( event ) {
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("drop", function( event ) {
  event.stopPropagation();
  event.preventDefault();
  var files = event.dataTransfer.files;
  for (var i = 0; i < files.length; i++) {
    div.textContent += files[i].name + ' ' + files[i].size + '位元組\n';
  }
}, false);
複製程式碼

上面程式碼中,通過dataTransfer.files屬性讀取被拖拉的檔案的資訊。如果想要讀取檔案內容,就要使用FileReader物件。

div.addEventListener('drop', function(e) {
  e.preventDefault();
  e.stopPropagation();

  var fileList = e.dataTransfer.files;
  if (fileList.length > 0) {
    var file = fileList[0];
    var reader = new FileReader();
    reader.onloadend = function(e) {
      if (e.target.readyState === FileReader.DONE) {
        var content = reader.result;
        div.innerHTML = 'File: ' + file.name + '\n\n' + content;
      }
    }
    reader.readAsBinaryString(file);
  }
});
複製程式碼

DataTransfer.types

屬性是一個只讀的陣列,每個成員是一個字串,裡面是拖拉的資料格式(通常是 MIME 值)。比如,如果拖拉的是文字,對應的成員就是text/plain。

四、DataTransfer 的例項方法

一、資源事件

  • DataTransfer.setData()方法用來設定拖拉事件所帶有的資料。該方法沒有返回值。
  • DataTransfer.getData()方法接受一個字串(表示資料型別)作為引數,返回事件所帶的指定型別的資料(通常是用setData方法新增的資料)。
  • DataTransfer.clearData()方法接受一個字串(表示資料型別)作為引數,刪除事件所帶的指定型別的資料。如果沒有指定型別,則刪除所有資料。如果指定型別不存在,則呼叫該方法不會產生任何效果。
  • DataTransfer.setDragImage()方法可以自定義跟隨滑鼠一起移動的圖片。它接受三個引數。第一個是JavaScript 複習之各類事件(二)節點或者節點,如果省略或為null,則使用被拖動的節點的外觀;第二個和第三個引數為滑鼠相對於該圖片左上角的橫座標和右座標。

其他事件

beforeunload事件

在視窗、文件、各種資源將要解除安裝前觸發。它可以用來防止使用者不小心解除安裝資源。

unload 事件

在視窗關閉或者document物件將要解除安裝時觸發。它的觸發順序排在beforeunloadpagehide事件後面。

load 事件,error 事件

load事件在頁面或某個資源載入成功時觸發。error事件是在頁面或資源載入失敗時觸發。abort事件在使用者取消載入時觸發。

二、session歷史事件

pageshow 事件,pagehide 事件

預設情況下,瀏覽器會在當前會話(session)快取頁面,當使用者點選“前進/後退”按鈕時,瀏覽器就會從快取中載入頁面。

pageshow 事件在頁面載入時觸發,包括第一次載入和從快取載入兩種情況。如果要指定頁面每次載入(不管是不是從瀏覽器快取)時都執行的程式碼,可以放在這個事件的監聽函式。 pageshow 事件有一個persisted屬性,返回一個布林值。頁面第一次載入時,這個屬性是false;當頁面從快取載入時,這個屬性是true

pagehide事件與pageshow事件類似,當使用者通過“前進/後退”按鈕,離開當前頁面時觸發。它與 unload 事件的區別在於,如果在 window 物件上定義unload事件的監聽函式之後,頁面不會儲存在快取中,而使用pagehide事件,頁面會儲存在快取中。pagehide事件例項也有一個persisted屬性,將這個屬性設為true,就表示頁面要儲存在快取中;設為false,表示網頁不儲存在快取中,這時如果設定了unload 事件的監聽函式,該函式將在 pagehide 事件後立即執行。

popstate 事件

popstate事件在瀏覽器的history物件的當前記錄發生顯式切換時觸發。注意,呼叫history.pushState()history.replaceState(),並不會觸發popstate事件。該事件只在使用者在history記錄之間顯式切換時觸發,比如滑鼠點選“後退/前進”按鈕,或者在指令碼中呼叫history.back()history.forward()history.go()時觸發。

hashchange 事件

事件在 URL 的 hash 部分(即#號後面的部分,包括#號)發生變化時觸發。該事件一般在window物件上監聽。

hashchange的事件例項具有兩個特有屬性:oldURL屬性和newURL屬性,分別表示變化前後的完整 URL

三、網頁狀態事件

DOMContentLoaded事件

網頁下載並解析完成以後,瀏覽器就會在document物件上觸發 DOMContentLoaded 事件。

readystatechange事件

當 Document 物件和 XMLHttpRequest 物件的readyState屬性發生變化時觸發。document.readyState有三個可能的值:loading(網頁正在載入)、interactive(網頁已經解析完成,但是外部資源仍然處在載入狀態)和complete(網頁和所有外部資源已經結束載入,load事件即將觸發)。

四、視窗事件

scroll事件

在文件或文件元素滾動時觸發,主要出現在使用者拖動滾動條。

resize事件

在改變瀏覽器視窗大小時觸發,主要發生在window物件上面。

fullscreenchange事件,fullscreenerror事件

fullscreenchange事件在進入或推出全屏狀態時觸發,該事件發生在document物件上面。

fullscreenerror事件在瀏覽器無法切換到全屏狀態時觸發。

五、剪下板事件

  • cut:將選中的內容從文件中移除,加入剪下板時觸發
  • copy:進行復制動作時觸發
  • paste:剪下板內容貼上到文件後觸發

六、焦點事件

  • focus:元素節點獲得焦點後觸發,該事件不會冒泡。
  • blur:元素節點失去焦點後觸發,該事件不會冒泡。
  • focusin:元素節點將要獲得焦點時觸發,發生在focus事件之前。該事件會冒泡。
  • focusout:元素節點將要失去焦點時觸發,發生在blur事件之前。該事件會冒泡。

這四個事件都繼承了FocusEvent介面。FocusEvent例項具有以下屬性。

  • FocusEvent.target:事件的目標節點。
  • FocusEvent.relatedTarget:對於focusin事件,返回失去焦點的節點;對於focusout事件,返回將要接受焦點的節點;對於focus和blur事件,返回null。

由於focus和blur事件不會冒泡,只能在捕獲階段觸發,所以addEventListener方法的第三個引數需要設為true。

相關文章