jQuery Clone Bug解决代码

  首先,jQuery事件绑定的时候,所有事件用$.data()方法存储到了$.cache里面,用data('events')可以反复获取到它们:

  

复制代码 代码如下:

  var $div = $('div.demo'), data = $div.data();

  // 获取所有绑定事件:

  var events = data.events;

  // 除了window对象绑定事件的比较特殊:

  var windowEvents = $(window).data('__events__');

  在必要的时候,可以检索有没有绑定相关处理函数:

  

复制代码 代码如下:

  var clickHandler = function(){

  console.log('click test');

  };

  $div.click(clickHandler);

  events.click.some(function(ev){

  return ev.handler === clickHandler;

  });

  BUG示例

  

复制代码 代码如下:

  <script type="text/javascript">

  Array.prototype.xyzz = function (arg) {

  console.log(1,this,arg);

  };

  Array.prototype.xyzzz = function (arg) {

  console.log(2,this,arg);

  };

  $(function() {

  $('button').click(function () {

  $('div.demo').clone(true).appendTo( 'body' );

  })

  $('div.demo').click(function () {

  console.log('click..');

  })

  });

  </script>

  BUG来源

  

复制代码 代码如下:

  // event.js, jQuery.event.add:

  // jQuery 1.4.1

  handlers = events[ type ] = {};

  // jQuery 1.4.2+

  handlers = events[ type ] = [];

  // manipulation.js, jQuery.clone : , cloneCopyEvent():

  for ( var type in events ) {

  for ( var handler in events[ type ] ) {

  jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );

  }

  }

  在1.4.2之后,events[ type ]为数组,for...in循环会获取到数组原型上扩展的所有方法,接着绑定到DOM对象上。

  解决

  不扩展数组原型,不使用clone(true)方法。

  hasOwnProperty检查。

  使用each循环:

  

复制代码 代码如下:

  var self = this;

  for ( var type in events ) {

  jQuery.each(events[ type ],function(idx,evt) {

  jQuery.event.add( self, type, evt.handler, evt.data );

  });

  }

  完整演示代码:

  

复制代码 代码如下:

  <!DOCTYPE HTML>

  <html>

  <head>

  <meta charset="utf-8" />

  <title>jQuery Clone Bug</title>

  <style type="text/css">

  .demo{ margin:1em;background:#07a; height:10em; width:10em; }

  </style>

  </head>

  <body>

  <button>doClone</button>

  <a href="http://www.glzy8.com">返回</a>

  <div class="demo">click me</div>

  <script src="http://demo.glzy8.com/jslib/jquery/jquery-1.4.4.js"></script>

  <script type="text/javascript">

  Array.prototype.xyzz = function (arg) {

  console.log(1,this,arg);

  };

  Array.prototype.xyzzz = function (arg) {

  console.log(2,this,arg);

  };

  $(function() {

  $('button').click(function () {

  $('div.demo').clone(true).appendTo( 'body' );

  })

  $('div.demo').click(function () {

  console.log('click..');

  })

  });

  // var events = $('div.demo:eq(0)').data().events

  // manipulation.js : cloneCopyEvent

  // :line 372

  // for ( var type in events ) {

  // for ( var handler in events[ type ] ) {

  // console.log(handler);

  // }

  // }

  // console.log($.isArray(events['click']))

  // 原因

  // event.js : event.add

  // :line 106

  // handlers = events[ type ] = [];

  </script>

  </body>

  </html>

  在线演示 /js/jquery_clone_bug/jQuery_clone_bug_demo.htm