JavaScript常用的事件模型
一、事件绑定模型
DOM0事件模型
1.内联模型(行内绑定):将函数名直接作为HTML标签中事件属性的属性值
<button id="btn" onclick="func()">内联模型绑定</button>
缺点:不符合W3C中关于内容与行为分离的基本规范
2.脚本模型(动态绑定):通过在JS中选中某个节点,然后给节点添加onclick属性。
<button id="btn1">脚本模型绑定</button> <script> document.getElementById("btn1").onclick = function () { alert("123"); }; </script>
优点:符合W3C中关于内容与行为分离的基本规范,实现HTML与JS的分离。
3.DOM0共有缺点:
a.同一个节点只能添加一次同一事件,如果添加多次最后一个生效
b.通过DOM0绑定的事件,一旦绑定将无法取消(虽然行内绑定可以removeAttribute但不算)
DOM2事件模型
1.添加DOM2事件绑定:
①IE8之前,使用.attachEvent("onclick",func3);谷歌不支持这种写法
②IE8之后,使用.addEventListener("click",func3,true/false);
参数三:false(默认)表示事件冒泡;传入true 表示事件捕获;
③兼容所有浏览器的处理方式:
<button id="btn2">DOM2模型绑定</button> <script> var btn2 = document.getElementById("btn2"); if(btn2.attachEvent){ btn2.attachEvent("onclick",func3); }else{ btn2.addEventListener("click",func3); } function func3(){ alert("789"); } </script>
2.DOM2绑定的优点
①同一个节点可以绑定多个同类事件
<script> btn2.addEventListener("click",function(){ alert("第二次绑定click事件"); }); </script>
②使用DOM2绑定的事件可以有专门的函数进行事件取消
3.DOM2取消事件绑定:
①使用.attachEvent("onclick",func3);绑定,要用.detachEvent("onclick",func3);取消
②使用.addEventListener("click",func3);绑定,要用.removeEventListener("click",func3);取消
③兼容所欲浏览器的处理方式:
注意:如果DOM2绑定的事件,需要取消,则绑定事件时,回调函数必须是函数名,而不能是匿名函数。
因为取消事件时需要传入函数名进行取消
<button id="btn3">取消DOM2模型绑定</button> <script> var btn3 = document.getElementById("btn3"); btn3.onclick = function () { if(btn2.detachEvent){ btn2.detachEvent("onclick",func3); }else { btn2.removeEventListener("click",func3); } alert("事件已取消!"); }; </script>
二、事件流模型
1.事件冒泡(false或默认):当触发一个节点的事件时,会从当前节点开始,依次触发其祖先节点的同类型事件,直到DOM根节点
2.事件捕获(true):当触发一个节点的事件时,会从DOM根节点开始,依次触发其祖先节点的同类型事件,直到当前节点自身。
↓ DOM根节点 ↑
捕 冒
↓ 祖先节点 ↑
获 泡
↓ 当前节点 ↑
3.什么时候事件冒泡,什么时候事件捕获?
①当使用addEventListener绑定事件,第三个参数传入true时表示事件捕获;
②除此之外全都是事件冒泡
<body>
<div id="div1">1
<div id="div2">2
<div id="div3">3</div>
</div>
</div>
</body>
<script>
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
//事件冒泡 div1.addEventListener("click",function () { console.log("div1 click 1"); }); div2.addEventListener("click",function () { //myParagraphEventHandler(); console.log("div2 click 2") }); div3.addEventListener("click",function () { console.log("div3 click 3"); }); //事件捕获 div1.addEventListener("click",function () { console.log("div1 click 1"); },true); div2.addEventListener("click",function () { //myParagraphEventHandler(); console.log("div2 click 2") },true); div3.addEventListener("click",function () { console.log("div3 click 3"); },true);
</script>
4.阻止事件冒泡:
①IE10之前(包含10),使用:e.cancelBubble = true;
②IE10之后,使用:event.stopPropagation();
function myParagraphEventHandler(e) { e = e || window.event; if (e.stopPropagation) { e.stopPropagation(); //IE10以后和其他浏览器 } else { e.cancelBubble = true; //IE10以前(包含10) } }
5.阻止默认事件:
①IE10之前(包含10),使用:e.returnValue = false;
②IE10之后,使用:e.preventDefault();
<a href="01-事件笔记.html" onclick="func()">超链接</a> <script> function func(e) { e = e || window.event; eventHandler(e); alert("您点击了超链接但是您走不了哈哈哈哈哈!!!"); } //阻止默认事件的函数 function eventHandler(e) { e = e || window.event; // 防止默认行为 if (e.preventDefault) { e.preventDefault(); //IE10以后和其他浏览器 } else { e.returnValue = false; //IE10以前(包含10) } } </script>