事件處理函數
- 綁定事件 = 綁定事件的處理函數(事件本身是存在的,綁定的是相應的反饋)
- 事件 + 事件的反饋 = 前端交互 (前端核心)
綁定事件的方式
1. 句柄綁定
- 默認(只能)是事件冒泡這種事件流
- 為某一個元素(事件源)指定了一個事件句柄(onclick,事件發生時要進行的操作)
oDiv.onclick = function(){} // 事件句柄 = 處理函數
- onclick綁定的事件處理函數內寫的其他函數,在非嚴格模式下,指向的是window
- 【該方式】一個元素、同一事件、只能綁定一個事件處理函數(綁定多個取最后)
2. 內聯事件監聽器
在html上綁定,綁定執行(不建議使用,結構和邏輯應當分離),這種按屬性綁定的方式優先級更低,會被js覆蓋
3. 事件監聽器
1) W3C規范,但IE9以下不支持
- 注冊事件監聽器/綁定事件監聽器
- 可以綁定多個事件處理函數,都能執行;如果綁定了多次同一事件處理函數,只會執行一次
- 注意:事件類型沒有加
on
elem.addEventListener(事件類型,事件處理函數,false);//false事件冒泡 true事件捕獲
// 2種都執行
oBtn.addEventListener('click',function(){this.innerHTML = '加載中..'
},false)
oBtn.addEventListener('click',function(){console.log('加載更多事件')
},false)
oBtn.addEventListener('click',test,false);
oBtn.addEventListener('click',test,false);
function test(){console.log(1); // 打印1次
}
2)IE8及以下綁定方法
elem.attachEvent(事件類型,事件處理函數);
- 注意:事件類型加
on
點擊事件 + IIFE
- 在綁定時,console.log(i)并沒有執行,i沒有保存,綁定的函數在for循環結束后被執行(點擊了),訪問到的是5
var oLi = document.getElementsByTagName('li'),len = oLi.length,item;
for (var i = 0; i < len; i++) {(function (j) {item = oLi[i];item.addEventListener('click', function () {console.log(i);}, false);}(i))
}
3) 事件處理程序的運行環境 / this
- 誰調用this就指向誰(attachEven是個特例,this指向window)
4) 【兼容】封裝綁定事件處理函數
function addEvent(el, type, fn) {if (el.addEventListener) {el.addEventListener(type, fn, false);} else if (el.attachEvent) {el.attachEvent('on' + type, function () {fn.call(el);})} else {el['on' + type] = fn}
}
5)解除事件處理程序
// 句柄
element.onclick=null/false;// W3C規范事件監聽器 (add時怎么寫remove就得怎么寫)
element.addEventListener('click',test,false);
element.removeEventListener('click',test,false)// IE8及以下事件監聽器
element.detachEvent('onclick',test);
- 非嚴格模式下可以使用方法4
function removeEvent(elem, type, fn) {if (elem.addEventListener) {elem.removeEventListener(type, fn, false)} else if (elem.attachEvent) {elem.detachEvent('on' + type, fn)} else {elem['on' + type] = null}
}
標簽嵌套
- 內聯元素寫嵌套關系,dom解析出來依然不是嵌套的
- a的特殊現象,變成block依然不能嵌套
事件冒泡與捕獲
- dom結構中/嵌套結構中,從內到外,從下到上,事件從子元素一層一層向上傳遞的現象是事件冒泡
- 需綁定相同事件,向上傳遞時,父級有相同事件則觸發
- 關心的是事件,而非事件處理函數
- 事件捕獲則順序相反,點擊父元素,一直捕獲到事件源,
事件監聽器true
- 注意:dom結構嵌套,視覺上并不一定嵌套
- 點擊黃色:事件捕獲先于事件冒泡執行
- 點擊紅色,紅色是事件源,事件源是按綁定順序先后執行的,非冒泡非捕獲
focus、blur、change、submit、reset、select
這些是沒有捕獲和冒泡事件的- IE瀏覽器是沒有事件捕獲的,除了Chrome以外的老版本瀏覽器都沒有捕獲,新版的瀏覽器(火狐、歐朋)有捕獲的,主要和webkit blink內核有關系
取消冒泡
1. e.stopPropagation() (W3C)
2. e.cancelBuble = true (IE)
- attach的怎么取消
3. 【兼容】封裝
function cacelBubble(e) {var e = e || window.event;if (e.stopPropagation) {e.stopPropagation();} else {e.cancelBubble = true;}
}
取消默認事件
1. 阻止右鍵菜單彈出
1)阻止右鍵菜單彈出
2)W3C:e.preventDefault()(IE9不兼容)
3)e.returnValue = false
function preventDefaultEvent(e) {var e = e || window.event;if (e.preventDefault) {e.preventDefault()} else {e.returnValue = false}
}
2. a標簽默認事件
- 跳轉和刷新頁面
// 1)void(0)相當于return 0
<a href = "javascript:void(0)">百度一下</a>
// 2)
<a href = "javascript:;">百度一下</a>
// 3)錨點方式
<a href = "#">百度一下</a>
// 4)
a.onclick = function(e){e.preventDefault();
}
舉例