一起來啃犀牛書:事件處理
《javascript權威指南》這本書就像是js界的聖經,對於大神和新手都應該是必讀書。但是這本近千頁的書已經厚到讓人望而生畏,要通讀它不僅要時間也需要毅力。爲了提升自己在js語言上的深度,所以抱着工匠精神開始研讀,此文包含書中實用性較強的一些知識點和代碼,算做讀書筆記吧~
這一章參照的是W3C定義的3級DOM事件,現在更名爲UI事件了。
文檔加載事件
知識點
- load。直到文檔和所有圖片加載完畢時才發生
- DOMContentLoaded。當文檔加載解析完畢且所有延遲腳本都執行完畢時會出發。優先使用
- readystatechange。HTML5標準化的事件,在load事件之前觸發。
例題
定義whenReady函數,類似onLoad函數。當文檔就緒時,傳遞給whenReady的函數就會作爲Document對象的方法調用。優先使用DOMContentLoaded和readystatechange事件。
代碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
var whenReady = (function(){ var funcs = [], //需要運行的函數 ready = false, //爲避免重複執行 i = 0; function handler(e) { if(!ready) { //如果發生readystatechange事件,但狀態不是complete則文檔未準備好 if('readystatechange'===e.type && 'complete'!==document.readyState) { return ; } for (i=0;i<funcs.length; i++) { funcs[i].call(document); } ready = true; funcs = null; } } if(document.addEventListener) { document.addEventListener('DOMContentLoaded', handler); document.addEventListener('readystatechange', handler); window.addEventListener('load', handler); } else if(document.attachEvent) { document.attachEvent('onreadystatechange', handler); window.attachEvent('load', handler); } return function(f){ if (ready) f.call(document); //若準備完畢則運行 else funcs.push(f); //否則加入隊列 } }()); |
鼠標事件
知識點
事件屬性
- clientX和clientY表示鼠標座標
- altKey、metaKey、ctrlKey、shiftKey
- HTML5中元素添加draggable屬性之後就可以實現dragstart和dragend事件。
例題
定義drag函數實現文檔元素拖動操作。
代碼
drag函數綁定到mousedown事件,整個邏輯也是比較簡單在mousedown事件開始時記錄座標點,然後在mousemove事件時改變css樣式來實現dom元素移動,同時結束時註銷事件。不過需要注意的就是dom元素必須是非靜態定位。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
function drag(){ //獲取座標 function getScrollOffsets(w) { var d = {}; //使用指定窗口或者當前窗口 w = w || window; //現代瀏覽器 if (w.pageXOffest != null) { return { x: w.pageXOffest, y: w.pageYOffset }; } //標準模式下的IE d = w.document; if (document.compatMode === 'CSS1Compat') { return { x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop }; } //怪醫模式下的瀏覽器 return { x: d.body.scrollLeft, y: d.body.scrollTop }; } var scroll = getScrollOffsets(); var startX = event.clientX + scroll.x; var startY = event.clientY + scroll.y; var origX = elementToDrag.offsetLeft; var origY = elementToDrag.offsetTop; var deltaX = startX - origX; var deltaY = startY - origY; //註冊鼠標移動和鼠標釋放事件 if (document.addEventListener) { document.addEventListener("mousemove", moveHandler, true); document.addEventListener("mouseup", upHandler, true) } else if (document.attachEvent) { elementToDrag.setCapture(); elementToDrag.attachEvent("onmousemove", moveHandler); elementToDrag.attachEvent("onmouseup", upHandler); elementToDrag.attachEvent("onlosecapture", upHandler) } if (event.stopPropagation) event.stopPropagation(); else event.cancelBubble = true; if (event.preventDefault) event.preventDefault(); else event.returnValue = false; //移動鼠標時移動元素 function moveHandler(e) { if (!e) e = window.event; var scroll = getScrollOffsets(); elementToDrag.style.left = (e.clientX + scroll.x - deltaX) + "px"; elementToDrag.style.top = (e.clientY + scroll.y - deltaY) + "px"; if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true } //拖拽結束,註銷事件 function upHandler(e) { if (!e) e = window.event; if (document.removeEventListener) { document.removeEventListener("mouseup", upHandler, true); document.removeEventListener("mousemove", moveHandler, true) } else if (document.detachEvent) { elementToDrag.detachEvent("onlosecapture", upHandler); elementToDrag.detachEvent("onmouseup", upHandler); elementToDrag.detachEvent("onmousemove", moveHandler); elementToDrag.releaseCapture() } if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true } } |
文本/鍵盤事件
知識點
- keypress。常用的高級鍵盤事件。
- textinput。時3級DOM事件規範定義的通用事件(來源包括鍵盤/粘貼/拖放/聲音/手寫)
- textInput。webkit瀏覽器支持類似textinput的事件。
例題1
寫一個過濾鍵盤輸入的函數,當用戶輸入了不允許字符時顯示消息元素,否則隱藏它。
代碼1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
(function() {
var inputelts = document.getElementsByTagName("input");
for (var i = 0; i < inputelts.length; i++) {
var elt = inputelts[i];
if (elt.type != "text" || !elt.getAttribute("data-allowed-chars")) continue;
if (elt.addEventListener) {
elt.addEventListener("keypress", filter, false);
elt.addEventListener("textInput", filter, false);
elt.addEventListener("textinput", filter, false)
} else {
elt.attachEvent("onkeypress", filter)
}
}
function filter(event) {
var e = event || window.event;
var target = e.target || e.srcElement;
var text = null;
if (e.type === "textinput" || e.type === "textInput") text = e.data;
else {
var code = e.charCode || e.keyCode;
if (code < 32 || e.charCode == 0 || e.ctrlKey || e.altKey) return;
var text = String.fromCharCode(code)
}
var allowed = target.getAttribute("data-allowed-chars");
var messageid = target.getAttribute("data-messageid");
if (messageid) var messageElement = document.getElementById(messageid);
for (var i = 0; i < text.length; i++) {
var c = text.charAt(i);
if (allowed.indexOf(c) == -1) {
if (messageElement) messageElement.style.visibility = "visible";
if (e.preventDefault) e.preventDefault();
if (e.returnValue) e.returnValue = false;
return false
}
}
if (messageElement) messageElement.style.visibility = "hidden"
}
}());
|
例題2
將輸入的字符自動轉換爲大寫
代碼2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function forceToUpperCase(element) { if (typeof element === "string") element = document.getElementById(element); element.oninput = upcase; element.onpropertychange = upcaseOnPropertyChange; function upcase(event) { this.value = this.value.toUpperCase() } function upcaseOnPropertyChange(event) { var e = event || window.event; if (e.propertyName === "value") { this.onpropertychange = null; this.value = this.value.toUpperCase(); this.onpropertychange = upcaseOnPropertyChange } } } |
事件處理
事件代理
節省內存,適用於表格/列表等重複性dom元素。基本原理就是將事件綁定到祖先元素上,然後判斷事件對象target,如果爲對應的子元素則執行對應的邏輯。
事件創建/分發
1 2 3 4 |
var event = document.createEvent('Event'); event.initEvent('click'); var element = document.getElementById('zdl'); element.dispatchEvent(event); |
最後
這本書真是內容翔實,枯燥難讀。這一章的內容看了幾遍才決定以百度腦圖和代碼實例相結合的方式,如果有更好的建議可以發送郵件給我~感謝閱讀