高级事件(二)

   事件委托

   什么是事件委托?用现实中的理解就是:有100个学生同时在某天中午收到快递,但这100个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生。而在jQuery中,我们通过事件冒泡的特性,让子元素绑定的事件冒泡到父元素(或祖先元素)上,然后再进行相关处理即可。

   如果一个企业级应用做报表处理,表格有2000行,每一行都有一个按钮处理。如果用之前的.bind()处理,那么就需要绑定2000个事件,就好比2000个学生同时站在学校门口等
快递,不但会堵塞路口,还会发生各种意外。这种情况放到页面上也是一样,可能导致页面极度变慢或直接异常。而且2000个按钮使用ajax分页的话,.bind()方法无法动态绑定
未存在的元素。就好比,新转学的学生,快递员无法验证他的身份,就可能收不到快递。

   有html代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>高级事件</title>
    <script type="text/javascript" src="jquery-1.12.3.js"></script>
    <script type="text/javascript" src="jquery-migrate-1.2.1.js"></script>
    <script type="text/javascript" src="demo.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
    <div style=" 200px; height: 200px; background: green;" id="box">
        <input type="button" class="button" value="按钮" />
    </div>
</body>
</html>

   使用.bind()绑定一个事件:

$(".button").bind("click", function() {
    alert("事件不委托!");
});

   也可使用.live()绑定一个事件:

$(".button").live("click", function() {
    alert("事件委托!");
});

   但要注意:使用live绑定的是document,而非button,所以永远只会绑定一次事件!

   使用.bind()不具备动态绑定功能,只有点击原始按钮才能生成:

//bind无法动态绑定事件
$(".button").bind("click", function() {
    $(this).clone().appendTo("#box");
});

   使用.live()具备动态绑定功能,jQuery1.3使用,jQuery1.7之后废弃,jQuery1.9删除,所以还需引入向下兼容插件——jquery-migrate-1.2.1.js

//live可以动态绑定事件,因为事件绑定在document上
$(".button").live("click", function() {
    $(this).clone().appendTo("#box");
});

   .live()原理就是把click事件绑定到祖先元素$(document)上,而只需要给$(document)绑定一次即可,而非2000次,然后就可以处理后续动态加载的按钮的单击事件。在接受任何事件时,$(document)对象都会检查事件类型(event.type)和事件目标(event.target),如果click事件是.button,那么就执行委托给它的处理程序,.live()方法已经被删除,无法使用了,需要测试使用的话,需要引入向下兼容插件。

   一句话总结:live绑定在document上,而点击button其实是冒泡到document上,并且点击document时候,需要验证event.type和event.target才能触发。

   .live()无法使用链接连缀调用,因为参数的特性导致。即下列代码无效:

//live是不支持元素连缀调用的
$("#box").children(0).live("click", function() {
    $(this).clone().appendTo("#box");
});

   在上面的例子中,我们使用了.clone()克隆。其实如果想把事件行为复制过来,我们只需要传递true即可:.clone(true),这样也能实现类似事件委托的功能,但原理却截然不同,一个是复制事件行为,一个是事件委托,而在非克隆操作下,此类功能只能使用事件委托。

$(".button").bind("click", function() {
    $(this).clone(true).appendTo("#box"); //其实是复制事件行为
});

   在非克隆操作下,此类功能只能使用事件委托:

$(".button").live("click", function() {
    $('<input type="button" class="button" value="按钮" />').appendTo("#box");
});

   或

$(".button").live("click", function() {
    $('<input type="button" class="button" value="按钮" />').clone(true).appendTo("#box");
});

   又或

$(".button").live("click", function() {
    $('<input type="button" class="button" value="按钮" />').clone().appendTo("#box");
});

   如果使用.bind()复制事件行为,则无法动态绑定:

$(".button").bind("click", function() {
    $('<input type="button" class="button" value="按钮" />').clone(true).appendTo("#box");
});

   当我们需要停止事件委托的时候,可以使用.die()来取消掉。

$(".button").live("click", function() {
    $(this).clone().appendTo("#box");
}); 
$(".button").die("click"); //和unbind一个意思

   由于.live()和.die()在jQuery1.4.3版本中废弃了,之后推出语义清晰、 减少冒泡传播层次、又支持链接连缀调用方式的方法:.delegate()和.undelegate(),但这个方法在 jQuery1.7版本中被.on()方法整合替代了。

$("#box").delegate(".button", "click", function() {
    $(this).clone().appendTo("#box");
});
$("#box").undelegate(".button", "click");

   live的替代方法delegate(),live语义不清晰,由于它没有指定绑定谁,所以不清晰;而delegate语义清晰,绑定谁,谁就在开头。

   支持连缀调用方式:

$("div").first().delegate(".button", "click", function() {
    $(this).clone().appendTo("div:first");
});

   注意:.delegate()需要指定父元素,然后第一个参数是当前元素,第二个参数是事件方式,第三个参数是执行函数。和.bind()方法一样,可以传递额外参数,.undelegate()和.unbind()方法一样可以直接删除所有事件,比如:.undelegate('click'),也可以删除命名空间的事件,比如:.undelegate('click.abc')。

   注意:.live()和.delegate()和.bind()方法一样都是事件绑定,那么区别也很明显,用途上遵循两个规则:

  1. 在DOM中很多元素绑定相同事件时
  2. 在DOM中尚不存在即将生成的元素绑定事件时。

   我们推荐使用事件委托的绑定方式,否则推荐使用.bind()的普通绑定。

   on、off和one

   目前绑定事件和解绑的方法有三组共六个。由于这三组的共存可能会造成一定的混乱,为此jQuery1.7以后推出了.on()和.off()方法彻底摒弃前面三组。

   html代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>高级事件</title>
    <script type="text/javascript" src="jquery-1.12.3.js"></script>
    <script type="text/javascript" src="jquery-migrate-1.2.1.js"></script>
    <script type="text/javascript" src="demo.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
    <div style=" 200px; height: 200px; background: green;" id="box">
         <input type="button" class="button" value="按钮" />
    </div>
</body>
</html>

   替代.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(e) {
    alert("移入移出");
});

   替代.bind()方式,以对象模式绑定多个事件:

$(".button").on({
    mouseover:function() {
        alert("移入");
    },
    mouseout:function() {
        alert("移出");
    }
});

   又html代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>高级事件</title>
    <script type="text/javascript" src="jquery-1.12.3.js"></script>
    <script type="text/javascript" src="jquery-migrate-1.2.1.js"></script>
    <script type="text/javascript" src="demo.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
    <form action="123.html">
        <div style=" 200px; height: 200px; background: green;" id="box">
            <input type="submit" class="button" value="按钮" />
        </div>
    </form>
</body>
</html>

   替代.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").on("click", function() {
    alert("替代bind");
});
$(".button").off("click");

   替代.live()和.delegate(),事件委托:

$("#box").on("click",".button",function() {
    $(this).clone().appendTo("#box");
});

   替代.die()和.undelegate(),取消事件委托:

//替代.live .delegate
$("#box").on("click",".button",function() {
    $(this).clone().appendTo("#box");
});
//移除事件委托
$("#box").off("click",".button");

   注意:和之前方式一样,事件委托和取消事件委托也有各种搭配方式,比如额外数据、命名空间等等,这里不在赘述。

   不管是.bind()还是.on(),绑定事件后都不是自动移除事件的,需要通过.unbind()和.off()来手工移除。jQuery 提供了.one()方法,绑定元素执行完毕后自动移除事件,one()方法仅触发一次事件。

   类似于.bind()只触发一次:

//仅一次事件触发
$(".button").one("click", function() {
    alert("仅一次事件触发");
});

   类似于.delegate()只触发一次:

$("#box").one("click",".button",function() {
    $(this).clone().appendTo("#box");
});
原文地址:https://www.cnblogs.com/yerenyuan/p/5429778.html