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

我发现了一些似乎有效的案例,另一些则没有。 例如下面的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> 

我的猜测是,你看到行为的差异,因为你的页面中的一些对象被dynamic地添加/删除,你需要委托事件处理,以便为新添加的对象自动生成事件。

在你的各种例子中,这里有两种基本types的行为:

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

以上三者都是在代码第一次运行时,将一个点击处理程序直接附加到页面中存在的每个button对象。 这些基本相同。 .click()语法只是一个快捷方式。 $body.find('button')在function上等同于$('button')因为它们都select了正文中的所有button。

注意:这些事件处理程序只会附加到第一次运行此代码时存在的button对象。 随后添加到文档的任何button对象将不会附加到它们的事件处理程序。

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

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

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

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

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

在更具体的代码示例中,假设bxRetrieveCustomer div不是dynamic创build的,您应该更改:

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

对此:

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

哪个仍然会被委托事件处理,但会更紧密地绑定事件处理程序更接近实际的对象,所以它会更有效地工作。

效率

至于哪个最好,取决于:

如果在运行事件绑定代码(您希望事件绑定到该事件绑定代码)之后创build了对象,那么您将需要在事后不dynamic创build的最接近的祖先对象上使用委派的事件处理。

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

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

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