【问题标题】:JQuery Event Handlers - What's the "Best" methodJQuery 事件处理程序 - 什么是“最佳”方法
【发布时间】:2012-03-16 00:38:09
【问题描述】:

在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";
    });
})();

我发现了一些情况,其中一种似乎有效而另一种无效。例如下面的 Handler 2 工作,而 Handler 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
}); 

这是 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>

【问题讨论】:

    标签: jquery


    【解决方案1】:

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

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

    行为 #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";
    });
    

    以上三个都直接在代码第一次运行时将点击处理程序附加到页面中存在的每个按钮对象。这些基本相同。 .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";
    });
    

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

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

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

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

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

    到这里:

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

    这仍将是委托事件处理,但会将事件处理程序绑定到更接近实际对象的位置,因此它会更有效地工作。

    效率

    至于哪个最好,这取决于:

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

    如果您有大量对象(即使它们是静态的),那么委托事件处理的安装效率会高得多,因为它为所有对象安装一个事件处理程序,而不是为每个单独的对象安装数千个事件处理程序。

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

    【讨论】:

      【解决方案2】:

      如果你想要最好,我可以推荐使用 .on() 因为你可以创建某种通用方法,通过传递参数(即事件名称)也可以将其重用于其他事件。我通常使用 .on()

      【讨论】:

        猜你喜欢
        • 2012-04-17
        • 1970-01-01
        • 2010-09-17
        • 2013-10-23
        • 1970-01-01
        • 2017-03-27
        • 1970-01-01
        相关资源
        最近更新 更多