JQuery事件处理程序 - 什么是"最佳"方法

Gar*_*rom 6 jquery

在JQuery中附加事件处理程序的以下方法之间有什么区别?

(function () {

    var $body = $("body");

    $('button').click(function () {
        console.log(this) + " - 1";
    });

    $('button').on('click', function () {
        console.log(this) + " - 2";
    });

    $(document).on('click', 'button', function () {
        console.log(this) + " - 3";
    });

    $body.on('click', 'button', function () {
        console.log(this) + " - 4";
    });

    $body.find('button').on('click', function () {
        console.log(this) + " - 5";
    });
})();
Run Code Online (Sandbox Code Playgroud)

我发现了一些似乎工作而另一个不工作的情况.例如处理程序2的下方,并工作一段时间的处理程序1一样.为了完成这项工作,我必须实现Handler 3,这显然效率较低.

$retrieveCust = $("#bxRetrieveCustomer");

// Handler 1
$retrieveCust.find(".icoX").on("click", function () {
    // DO SOMETHING
});

// Handler 2
$retrieveCust.find(".tag-open").on("click", function () {
    // DO SOMETHING
});

// Handler 3
$(document).on("click", ".tag-open", function (event) {
    // DO SOMETHING
}); 
Run Code Online (Sandbox Code Playgroud)

这是HTML

<div class="box" id="bxRetrieveCustomer">
<h1>RETREIVE CUSTOMER</h1>
<div class="icoX">X</div>
<div class="box-liner10">
    <table>
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Date of Birth</th>
            <th>Email</th>
            <th>password</th>
            <th></th>
        </tr>
        <!-- ko foreach: Customers -->
        <tr>
            <td data-bind="text: FirstName"></td>
            <td data-bind="text: LastName"></td>
            <td data-bind="text: DateOfBirth"></td>
            <td data-bind="text: Email"></td>
            <td data-bind="text: Pwd"></td>
            <td><a class="tag-open"></a></td>
        </tr>
        <!-- /ko -->
    </table>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)

jfr*_*d00 20

我的猜测是你看到了行为上的差异,因为你的页面中的某些对象是动态添加/删除的,你需要委托事件处理才能自动为新添加的对象提供事件.

在您的各种示例中,此处有两种基本类型的行为:

行为#1:静态事件绑定

$('button').click(function () {
    console.log(this) + " - 1";
});

$('button').on('click', function () {
    console.log(this) + " - 2";
});

$body.find('button').on('click', function () {
    console.log(this) + " - 5";
});
Run Code Online (Sandbox Code Playgroud)

以上三者都将点击处理程序直接附加到首次运行代码时页面中存在的每个按钮对象.这些基本相同.该.click()语法仅仅是一个捷径.在$body.find('button')功能上等同于$('button')因为两个选择身体内的所有按钮.

注意:这些事件处理程序仅附加到首次运行此代码时存在的按钮对象.随后添加到文档的任何按钮对象都不会附加事件处理程序.

行为#2:动态或委托事件绑定

$(document).on('click', 'button', function () {
    console.log(this) + " - 3";
});

$(document.body).on('click', 'button', function () {
    console.log(this) + " - 4";
});
Run Code Online (Sandbox Code Playgroud)

这两个使用委托事件处理来监视冒泡到文档或正文对象的点击.这些也是类似的.这些将处理源自按钮标记的任何单击事件.由于事件处理程序没有直接附加到按钮对象,因此按钮可以在页面中进出,并且任何时候存在的所有按钮对象都将获得此处理程序行为.

通常不建议绑定绑定到documentbody对象的委托方法.事实上,这就是为什么.live()被弃用的原因,因为它就是它所做的,它可能会导致性能问题.问题是如果你得到许多委托事件都绑定到同一个对象,那么每次事件发生并且它冒泡到这个对象时,jQuery必须将原始选择器与许多不同的选择器进行比较,以查看哪个处理程序呼叫.

将委托事件绑定到尽可能接近实际目标对象的父对象要好得多,但显然你必须选择一个不会被添加/删除的父对象(你需要一个不断在页面中的对象) ).

在更具体的代码示例中,假设bxRetrieveCustomerdiv不是动态创建的,您应该更改:

$(document).on("click", ".tag-open", function (event) {
    // DO SOMETHING
}); 
Run Code Online (Sandbox Code Playgroud)

对此:

$("#bxRetrieveCustomer").on("click", ".tag-open", function (event) {
    // DO SOMETHING
}); 
Run Code Online (Sandbox Code Playgroud)

哪个仍将被委托事件处理,但会将事件处理程序绑定到更接近实际对象,以便更有效地工作.

效率

至于哪个最好,取决于:

如果您运行了希望事件绑定到的事件绑定代码后创建的对象,那么您将希望在最近的事件之后动态创建的最近的祖先对象上使用委托事件处理.

如果你有非常多的对象(即使它们是静态的),那么委托事件处理将更有效地安装,因为它为所有对象安装了一个事件处理程序,而不是为每个单独的对象安装了数千个事件处理程序.

如果您有中等或少量的静态对象,则将事件处理程序直接绑定到它们是最有效的.最初将事件处理程序绑定到每个对象需要花费更多的时间,但在事件发生时效率最高.