jquery event事件

Cloning Nodes

This time, we'll take a look at re-binding event handlers. But before we do, I should mention that, as of jQuery version 1.2, event handlers can be cloned along with elements. Consider this unordered list:

现在,我们就来说说重绑定事件处理函数。但是在我们做之前,我必须提醒,jq1.2版本,元素的事件函数已经可以克隆,我们看看下面的无序列表:

 

HTML:
  1. <ul id="list3" class="eventlist">
  2.   <li>plain </li>
  3.   <li class="special">special <button>I am special </button></li>
  4.   <li>plain </li>
  5. </ul>

 

We can make a copy of <li class="special"> and insert it after the original, while at the same time retaining any event handlers that were attached within the original. The plain .clone() method doesn't work that way; instead, it just copies the element:

我们可以拷贝<li class="special">并把他们插入到被鼠标点击的元素(以下我们简称original)的的背后。同时我们保留original的任何事件处理函数,但是clone()通过这种方法是不能运行的。相反,它只是简单的拷贝元素。

JavaScript:
  1. $ (document ). ready ( function ( ) {
  2.   $ ( '#list3 li.special button' ). click ( function ( ) {
  3.     var $parent = $ ( this ). parent ( );
  4.     $parent. clone ( ). insertAfter ($parent );
  5.   } );
  6. } );

As you can see, the original button is able to keep creating new list items, but the buttons inside the "dynamically generated" list items can't create new ones.

To get the event handlers copied over as well, all we have to do is pass in true to the method's single argument:

你可以看到,the original按钮可以创建新项目,但是动态生成的按钮却不可以。

为了把事件处理函数也同样被拷贝,我们可以在clone方法里面加true。例子:

JavaScript:
  1. $ (document ). ready ( function ( ) {
  2.   $ ( '#list4 li.special button' ). click ( function ( ) {
  3.     var $parent = $ ( this ). parent ( );
  4.     $parent. clone ( true ). append ( ' I/'m a clone!' ). insertAfter ($parent );
  5.   } );
  6. } );

 

Note: I've added .append(' I/'m a clone!') here only as visual reinforcement of what is going on.

 

Using .clone(true) is great when we want to make a copy of existing elements and their event handlers, but there are plenty of other situations that don't involve cloning in which we might want event handlers to persist.

但我们想拷贝已经存在的元素和他们的事件事,使用clone()方法是不错的方法,但是这里有许多情况是通过clone不能做到的。

Re-binding Basics(重绑定)

The basic concept behind re-binding is fairly straightforward: We create a function that binds the handlers and then call it whenever new elements are introduced. For example, with our unordered list above, we first create a function called addItem that registers the click handler, which in turn will add a new item:

重绑定的基本概念是非常简单的:我们建立一个事件处理函数,元素无论在什么时候建立都可以可以调用它们(事件处理函数)。例如,在我们上面的无序列表中,我们可以建立一个名叫addItem的函数,并记录clik事件的处理函数,这是用来添加一个新项目的

JavaScript:
  1. function addItem ( ) {
  2.   $ ( '#list5 li.special button' ). click ( function ( ) {
  3.     var $newLi = $ ( '<li class="special">special and new <button>I am new</button></li>' );
  4.     $ ( this ). parent ( ). after ($newLi );
  5.   } );  
  6. }

 

Next, we call that function when the DOM initially loads:

我们在ready函数中调用它

JavaScript:
  1. $ (document ). ready ( function ( ) {
  2.   addItem ( );
  3. } );

 

Finally, we can call the function inside the click handler—and inside itself. That way, it will bind the event handlers to the new list item as well.

最后我们就可以调用click的事件处理函数和该函数本身(即addItem)。通过这种方法,我们可以为新项目绑定事件处理函数。

We'll add one more click handler to the button, but this one will not be re-bound, so that we can see the difference.

Here is what the code for buttons in #list5 looks like, all together:

我们可以再添加一个Click的事件处理函数,但是该事件处理函数是不可以重绑定的。这样,我们可以看到他们之间的不同。

JavaScript:
  1. function addItem ( ) {
  2.   $ ( '#list5 li.special button' ). click ( function ( ) {
  3.     var $newLi = $ ( '<li class="special">special and new <button>I am new</button></li>' );
  4.     $ ( this ). parent ( ). after ($newLi );
  5.     addItem ( );
  6.   } );
  7. }
  8.  
  9. $ (document ). ready ( function ( ) {
  10.   addItem ( );
  11.  
  12.   // non-rebinding click handler ...
  13.   $ ( '#list5 li.special button' ). click ( function ( ) {
  14.     $ ( this ). after ( ' pressed' );
  15.   } );
  16. } );

We can see that "pressed" is appended to the first list item each time it is clicked, but it is not appended to any of the list items created by our clicks. On the other hand, the created buttons are able to generate further list items because that function is being rebound.

我们可以看到"prssed"只添加到第一个按钮的后面(但这个按钮被点击的时候),但是其他按钮却没有。但是,这些新建的按钮却可以添加一个新的项目,也就是说,添加新项目的事件处理函数已经被绑定。

However, what we've just done produces unwelcome results if we click on a button more than once. The click handler is bound again with each click of a button, producing a multiplier effect. The first click of a button creates one extra list item; the second creates two; the third, four; and so on.

但是,当我们点击它的时候也产生了一些我们不要的结果。当我们点击一个按钮时,click事件处理函数也再绑定一次。也就是说数乘效应,当我们第一次点击按钮的时候,它新建了一个按钮。当我们再次点击该按钮的时候,它同时建立了两个按钮(我们可以看原创作者的例子),依此类推

 

 

Unbind, then Bind

为了解决数乘效应,我们可以先取消绑定,再绑定

To avoid the multiple binding, we can unbind fir st and then re-bind. So in line 2, instead of this ...

为了避免过多的绑定事件处理函数,产生数乘效应,我们可以先取消绑定,然后再重绑定。因此我们可以这样做:

$('#list5 li.special button').click(function() {

... we'll have this ...

$('#list6 li.special button').unbind('click').bind('click', function() {

Note the use of .bind() here. This is the universal event binder that jQuery uses. All the others, such as .click(), .blur(), .resize(), and so on, are shorthand methods for their .bind('event') equivalent.

The complete new code, again with the additional non-rebinding click handler for contrast, looks like this:

通过这种方法,每当我们点击按钮的时候,他就只建立一个新的项目。

JavaScript:
  1. function addItemUnbind ( ) {
  2.   $ ( '#list6 li.special button' )
  3.     . unbind ( 'click' )
  4.     . bind ( 'click' , function ( ) {
  5.       var $newLi = $ ( '<li class="special">special and new <button>I am new</button></li>' );
  6.       $ ( this ). parent ( ). after ($newLi );
  7.       addItemUnbind ( );
  8.   } );
  9. }
  10. $ (document ). ready ( function ( ) {
  11.   addItemUnbind ( );
  12.  
  13.   // non-rebinding click handler
  14.   $ ( '#list6 li.special button' ). click ( function ( ) {
  15.     $ ( this ). after ( ' pressed' );
  16.   } );
  17. } );

Unfortunately, our attempt to unbind the addItemUnbind() function went too far, unbinding the "non-rebinding" click handler as well, before it even had a chance to run once (it's evident because there is no "pressed" text after the "I am special" button here). Clearly, we're going to have to be more careful about what we're unbinding.

但是很抱歉的是,我们本来想取消addItemUnbind()函数的绑定,但是它连绑定"non-rebingding"事件处理函数也取消了。因此,我们对于取消绑定要慎重。
Event Namespacing

One way to avoid the over-reaching event unbinding is to apply a "namespace" to the click event for both binding and unbinding. So, instead of .bind('click') and .unbind('click), we'll have, for example, .bind('click.addit') and .unbind('click.addit). Here is one last code sample, which looks identical to the previous, except that it now has the namespaced event (and the list id is list7):

解决上面的bug的一个方法就是使用名称空间,通过下面的例子我们可以知道,它并没有取消"non-rebinding"的事件处理函数。

JavaScript:
  1. function addItemNS ( ) {
  2.   $ ( '#list7 li.special button' )
  3.     . unbind ( 'click.addit' )
  4.     . bind ( 'click.addit' , function ( ) {
  5.       var $newLi = $ ( '<li class="special">special and new <button>I am new</button></li>' );
  6.       $ ( this ). parent ( ). after ($newLi );
  7.       addItemNS ( );
  8.   } );
  9. }
  10. $ (document ). ready ( function ( ) {
  11.   addItemNS ( );
  12.  
  13.   // non-rebinding click handler
  14.   $ ( '#list7 li.special button' ). click ( function ( ) {
  15.     $ ( this ). after ( ' pressed' );
  16.   } );
  17. } );

For more information about event namespacing, read Brandon Aaron's article, Namespace Your Events.

Bonus: Unbind by Function Reference

我们也可以通过取消特定函数的重绑定来解决问题,例如取消CLICK事件的重绑定函数addItemFinal.这样就对'non-rebinding'事件处理函数没影响。

If you've made it this far, then you must have extraordinary patience, in which case I'll reward it with one final method of rebinding. Rather than namespace the events, we can reference the function in the second argument of the .bind() and .unbind() methods. We have to shuffle things around a bit to avoid "too much recursion," but it'll do just fine like so:

JavaScript:
  1. function addItemFinal ( ) {
  2.     var $newLi = $ ( '<li class="special">special and new <button>I am new</button></li>' );
  3.     $ ( this ). parent ( ). after ($newLi );
  4.     $ ( '#list8 li.special button' )
  5.       . unbind ( 'click' , addItemFinal )
  6.       . bind ( 'click' , addItemFinal );
  7. }
  8.  
  9. $ (document ). ready ( function ( ) {
  10. $ ( '#list8 li.special button' ). bind ( 'click' , addItemFinal );
  11.  
  12.   // non-rebinding click handler
  13.   $ ( '#list8 li.special button' ). click ( function ( ) {
  14.     $ ( this ). after ( ' pressed' );
  15.   } );
  16. } );

 

Note here that there are no parentheses after "addItemFinal" when it appears inside the bind/unbind, because we are referencing the function, not calling it. So let's test it out one last time:

In response to the comment by Nick Johns below, I'm providing an example that allows for both adding a row and removing a row. The code is based on the " Event Namespacing" example above:

下面是使用名称空间的例子:

JavaScript:
  1. function addRemoveItemNS ( ) {
  2.   var $newLi = $ ( '<li class="special">special and new <button class="addone">I am new</button> <button class="removeme">remove me</button></li>' );
  3.  
  4. $ ( '#list9 li.special' )
  5.   . find ( 'button.addone' )
  6.     . unbind ( 'click.addit' )
  7.     . bind ( 'click.addit' , function ( ) {
  8.       $ ( this ). parent ( ). after ($newLi );
  9.       addRemoveItemNS ( );
  10.   } )
  11.   . end ( )
  12.   . find ( 'button.removeme' )
  13.   . unbind ( 'click.removeit' )
  14.   . bind ( 'click.removeit' , function ( ) {
  15.     $ ( this ). parent ( ). remove ( );
  16.   } );
  17. }
  18.  
  19. $ (document ). ready ( function ( ) {
  20.   addRemoveItemNS ( );
  21. } );
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值