要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称。
目录:
-
[1、JavaScript 中事件绑定](#JavaScript 中事件绑定)
-
2、事件冒泡
-
[3、 jQuey中事件绑定](# jQuey中事件绑定)
一. 在DOM元素中直接绑定
#点击按钮显示弹出
<input type="button" onclick="alert('原生函数触发')" value="点我弹出警告框" />
#或者
<input type="button" onclick="MyAlert()" value="点我弹出警告框" />
<script type="text/javascript">
function MyAlert(){
alert("原生函数触发");
}
</script>
二. 在JavaScript代码中绑定
#为 id="demo" 的按钮绑定一个事件,显示它的 type 属性:
<input id="demo" type="button" value="点我显示 type 属性" />
<script type="text/javascript">
document.getElementById("demo").onclick=function(){
alert(this.getAttribute("type"));
}
</script>
#解绑事件
document.getElementById("demo").onclick= null;
如果为同一个元素同时绑定多个事件,前面的事件会被后面的事件覆盖,需指向相同的事件处理函数 **
<body>
<input type="button" value="" id="btn"/>
<script>
//为同一个元素绑定多个不同的事件,指向相同的事件处理函数
document.getElementById("btn").onclick = f1;
document.getElementById("btn").onmouseover = f1;
document.getElementById("btn").onmouseout = f1;
function f1(e) {
switch (e.type) {
case "click":
alert("1");
break;
case "mouseover":
this.style.backgroundColor = "red";
break;
case "mouseout":
this.style.backgroundColor = "green";
break;
}
}
</script>
</body>
三. 绑定事件监听函数
使用 addEventListener() 或 attachEvent() (兼容ie8)来绑定事件监听函数。(注:可以绑定多个事件)
addEventListener()函数语法:
elementObject.addEventListener(eventName,handle,useCapture);
参数说明:
- elementObject: DOM对象(即DOM元素)。
- eventName: 事件名称。注意,这里的事件名称没有“ on ”,如鼠标单击事件 click ,鼠标双击事件 doubleclick ,鼠标移入事件 mouseover,鼠标移出事件 mouseout 等。
- handle: 事件句柄函数,即用来处理事件的函数。 (注:函数名,不能带小括号)
- useCapture: Boolean类型,是否使用捕获,一般用false 。(默认冒泡)
function f1() {};
function f2() {};
document.getElementById("demo1").addEventListener("click", f1, false);
document.getElementById("demo2").addEventListener("click", f2, false);
//点击第二个按钮把第一个按钮的第一个点击事件解绑
document.getElementById("demo1").onclick = function () {
//解绑事件的时候,需要在绑定事件的时候,使用命名函数
document.getElementById("demo2").removeEventListener("click", f1, false);
};
attachEvent()函数语法:(不支持捕获)
elementObject.attachEvent(eventName,handle);
参数说明:
- elementObject: DOM对象(即DOM元素)。
- eventName: 事件名称。注意,与addEventListener()不同,这里的事件名称有“ on ”,如鼠标单击事件 onclick ,鼠标双击事件 ondoubleclick ,鼠标移入事件 onmouseover,鼠标移出事件 onmouseout 等。
- handle: 事件句柄函数,即用来处理事件的函数。(注:函数名,不能带小括号)
function f1() {};
function f2() {};
document.getElementById("demo1").attachEvent("onclick", f1);
document.getElementById("demo2").attachEvent("onclick", f2);
//点击第二个按钮把第一个按钮的第一个点击事件解绑
document.getElementById("demo1").onclick = function () {
//解绑事件的时候,需要在绑定事件的时候,使用命名函数
document.getElementById("demo2").detachEvent("onclick", f1);
};
addEventListener()是标准的绑定事件监听函数的方法,是W3C所支持的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支持该函数;但是,IE8.0及其以下版本不支持该方法,它使用attachEvent()来绑定事件监听函数。所以,这种绑定事件的方法必须要处理浏览器兼容问题。
#下面绑定事件的代码,进行了兼容性处理,能够被所有浏览器支持:
function addEvent(obj,type,handle){
try{ // Chrome、FireFox、Opera、Safari、IE9.0及其以上版本
obj.addEventListener(type,handle,false);
}catch(e){
try{ // IE8.0及其以下版本
obj.attachEvent('on' + type,handle);
}catch(e){ // 早期浏览器
obj['on' + type] = handle;
}
}
}
事件冒泡
多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的元素的事件触发了,外面的元素的该事件自动的触发了
#点击dv3会一次触发dv2、dv1
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function () {
console.log(this.id);
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
**阻止事件冒泡 **
#window.event.cancelBubble=true;
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function () {
console.log(this.id);
//阻止事件冒泡
// IE特有的,谷歌支持,火狐不支持
window.event.cancelBubble=true;
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
</script>
#e.stopPropagation();
<script>
document.getElementById("dv1").onclick = function () {
console.log(this.id);
};
document.getElementById("dv2").onclick = function (e) {
console.log(this.id);
//阻止事件冒泡
//谷歌和火狐支持
e.stopPropagation();
};
document.getElementById("dv3").onclick = function () {
console.log(this.id);
};
</script>
**事件阶段 **
通过e.eventPhase这个属性可以知道当前的事件是什么阶段,一般默认都是冒泡阶段,很少用捕获阶段,冒泡阶段从里向外,捕获阶段:从外向里
-
1---->捕获阶段
-
2---->目标阶段
-
3---->冒泡阶段
addEventListener方法的第三个参数是false的时候是冒泡阶段
addEventListener方法的第三个参数是true的时候是捕获阶段
<div id="dv1">
<div id="dv2">
<div id="dv3"></div>
</div>
</div>
<script>
//同时注册点击事件
var objs = [document.getElementById("dv3"), document.getElementById("dv2"), document.getElementById("dv1")];
//遍历注册事件
objs.forEach(function (ele) {
//为每个元素绑定事件
ele.addEventListener("click", function (e) {
console.log(this.id + "====>" + e.eventPhase);
}, false);
});
</script>
#参数false时点击dv3
dv3====>2,dv2====>3,dv2====>3
#参数true时点击dv3
dv1====>1,dv2====>1,dv2====>2
jQuery事件绑定
#不具备动态绑定功能,只有点击原始按钮才能生成
$("elem").bind('click',function (){ })
$("elem").unbind('click',function (){ })
#委托标签<a>,为新添加的标签绑定上事件
$("elem").delegate('a','click',function (){ })
$("elem").undelegate('a','click',function (){ })
#底层on方式
$("#elem").on('click',function(){})
$("#elem").off('click',function(){})
绑定事件on方法是jquery最底层处理方式,也是官方推荐绑定事件的一个方法
基本用法:
*.on( events ,[ selector ] ,[ data ] )*
多个事件绑定同一个函数:
$("#elem").on("mouseover mouseout",function(){ });
多个事件绑定不同函数:
$("#elem").on({
mouseover:function(){},
mouseout:function(){}
});
将数据传递到处理程序:
#通过第二参数(对象),当一个事件被触发时,要传递给事件处理函数的
function greet( event ) {
alert( "Hello " + event.data.name ); //Hello example
}
$( "button" ).on( "click", {
name: "example"
}, greet );
针对自己处理机制中,不仅有on方法,还有根据on演变出来的live方法(1.7后废弃),.delegate()方法等等。这些方法的底层实现部分还是on方法,这是利用了on的另一个事件机制委托的机制衍变而来的。
delegate()委托方法
$('#box').delegate('.button', 'click', function () {
$(this).clone().appendTo('#box');
});
$('#box').undelegate('.button','click');
//支持连缀调用方式
$('div').first().delegate('.button', 'click', function () {
$(this).clone().appendTo('div:first');
});
注意:.delegate()需要指定父元素,然后第一个参数是当前元素,第二个参数是事件方式,第三个参数是执行函数。和.bind()方法一样,可以传递额外参数。.undelegate()和.unbind()方法一样可以直接删除所有事件,比如:.undelegate('click')。也可以删除命名空间的事件,比如:.undelegate('click.abc')。
在DOM 中很多元素绑定相同事件时,或者DOM 中尚不存在即将生成的元素绑定事件时,我们推荐使用事件委托的绑定方式,否则推荐使用.bind()的普通绑定。
底层委托机制:
.on( events ,[ selector ] ,[ data ], handler(eventObject) )
第二参数中提供了一个selector选择器,简单的来描述下
<div class="left">
<p class="aaron">
<a>目标节点</a> //点击在这个元素上
</p>
</div>
$("div").on("click","p",fn)
事件绑定在最上层div元素上,当用户触发在a元素上,事件将往上冒泡,一直会冒泡在div元素上。如果提供了第二参数,那么事件在往上冒泡的过程中遇到了选择器匹配的元素,将会触发事件回调函数
卸载事件off()方法
根据on绑定事件的一些特性,off方法也可以通过相应的传递组合的事件名,名字空间,选择器或处理函数来移除绑定在元素上指定的事件处理函数。当有多个过滤参数时,只有与这些参数完全匹配的事件处理函数才会被移除。
绑定2个事件:
$("elem").on("mousedown mouseup",fn)
删除一个事件:
$("elem").off("mousedown")
删除所有事件:
$("elem").off("mousedown mouseup")
快捷方式删除所有事件,这里不需要传递事件名了,节点上绑定的所有事件讲全部销毁
$("elem").off()
目前绑定事件和解绑的方法有三组共六个。由于这三组的共存可能会造成一定的混乱,为此jQuery1.7 以后推出了.on()和.off()方法彻底摒弃前面三组。
//替代.bind()方式
$('.button').on('click', function () {
alert('替代.bind()');
});
//替代.bind()方式,并使用额外数据和事件对象
$('.button').on('click', {user : 'Lee'}, function (e) {
alert('替代.bind()' + e.data.user);
});
//替代.bind()方式,并绑定多个事件
$('.button').on('mouseover mouseout', function () {
alert('替代.bind()移入移出!');
});
//替代.bind()方式,以对象模式绑定多个事件
$('.button').on({
mouseover : function () {
alert('替代.bind()移入!');
},
mouseout : function () {
alert('替代.bind()移出!');
}
});
//替代.bind()方式,阻止默认行为并取消冒泡
$('form').on('submit', function () {
return false;
});
或
$('form').on('submit', false);
//替代.bind()方式,阻止默认行为
$('form').on('submit', function (e) {
e.preventDefault();
});
//替代.bind()方式,取消冒泡
$('form').on('submit', function (e) {
e.stopPropagation();
});
//替代.unbind()方式,移除事件
$('.button').off('click');
$('.button').off('click', fn);
$('.button').off('click.abc');
//替代.live()和.delegate(),事件委托
$('#box').on('click', '.button', function () {
$(this).clone().appendTo('#box');
});
//替代.die()和.undelegate(),取消事件委托
$('#box').off('click', '.button');
注意:和之前方式一样,事件委托和取消事件委托也有各种搭配方式,比如额外数据、命名空间等等,这里不在赘述。
不管是.bind()还是.on(),绑定事件后都不是自动移除事件的,需要通过.unbind()和.off()来手工移除。
jQuery 提供了.one()方法,绑定元素执行完毕后自动移除事件,可以方法仅触发一次的事件。
//类似于.bind()只触发一次
$('.button').one('click', function () {
alert('one 仅触发一次!');
});
//类似于.delegate()只触发一次
$('#box).one('click', 'click', function () {
alert('one 仅触发一次!');
});