文档章节

jquery事件绑定丢失

cyper
 cyper
发布于 2015/12/01 22:27
字数 697
阅读 74
收藏 0

##出现问题的代码

<!DOCTYPE html>
<html>
<head>
	<script src="https://code.jquery.com/jquery-1.11.3.js"></script>

	<meta charset="utf-8">
	<title>JS Bin</title>
	
	
</head>
<body>
	<script>
		var el = $("<div>lol</div>");

		el.click(function() {
			alert("hi"); 
		});

		$("body").html(el);
		$("body").html(el);

	</script>
</body>
</html>

点击页面上的lol。。并不会弹出alert框架,这是为什么??

##解决

原文:http://tbranyen.com/post/missing-jquery-events-while-rendering

While fixing some bugs within my Backbone.LayoutManager plugin, I found an odd behavior in the way I encouraged users to attach a rendered layout into the DOM. Since you can reuse a layout and it's simply a DIV node created by Backbone, I figured it was sufficient to simply have a user call jQuery's html method to inject it into the correct container.

An example of what that code looks like:

// A callback function would fire with a DOM Node
callback(function(domNode) {
  $("body").html(domNode);
});

This code looks completely valid and not likely to cause any immediate problems, however this is not the case. The issue is that all events would be removed upon a second render. So the first call to $("body").html(el) would work exactly as expected with all events functioning, but the second call to $("body").html(el) would result in no events firing.

I brought this issue to the attention of jQuery committer Dave Methvin who insisted that this was not a bug and that inserting a DOM element into the DOM using the jQuery html function was not a supported signature in the API.

This was confusing to me as I have always seen and used the html function in this way. After learning from Dave that I should be using $("body").empty().append(el), I went back to my code and implemented swapping using empty.

Unfortunately, no dice.

The events were still disappearing, so I made a reduced test case that looked something like this:

var el = $("<div>lol</div>");
 
el.click(function() {
   alert("hi"); 
});
 
$("body").empty().append(el);
$("body").empty().append(el);

Since the following code yields missing events, this proved to me that something was happening inside the empty method. Sure enough digging into that function yields the following code:

// Remove element nodes and prevent memory leaks
if ( elem.nodeType === 1 ) {
  jQuery.cleanData( elem.getElementsByTagName("*") );
}

The call to jQuery.cleanData removes all events from the element, in this case the "body" element. Since this is a shared reference to the exact same DOM node, that means when you re-attach to the DOM a second time it's not going to get it's events back.

Problem detected and understood, but how to fix?

Luckily the fix is really simple and is now implemented inside of the LayoutManager plugin. Since the call to empty or html only remove events from elements inside the DOM we can easily "detach" using the jQuery detach method in between renders. The updated working code from the reduced test case looks like this:

var el = $( "<div>lol</div>");
 
el.click( function() {
   alert( "hi"); 
});
 
$( "body").empty().append(el);
el.detach();
$( "body").empty().append(el);

This may be a very obvious problem and solution to many developers, but it bit me and I've talked to many other developers lately who have been having this same issue while using Backbone.js. It may be that many client side developers do not reuse the same DOM node, avoiding this issue.

##评论中的进一步解释: detach works because it removes the element from the DOM completely, but retains any data set on it by jQuery, which includes events. Since its removed from the DOM, empty doesn't see the element and doesn't remove the events. If you used remove instead of detach events would be removed there as well.

© 著作权归作者所有

共有 人打赏支持
上一篇: Backbonejs经验总结
下一篇: side menu待研究
cyper

cyper

粉丝 58
博文 685
码字总数 143207
作品 0
武汉
前端工程师
私信 提问
jQuery基础 - 常用基本属性

jQuery简介 jQuery 是一个 JavaScript 库,极大地简化了 JavaScript 编程 jQuery 对象是通过jQuery包装DOM对象后产生的对象,jQuery对象是jQuery独有的,如果一个对象就是jQuery对象,那么它...

ZHAO_JH
2018/07/31
0
0
第78天:jQuery事件总结(一)

jQuery事件总结(一)   现在就一点一点积累自己的知识体系,记录自己学到的和自己所理解的jQuery。   JavaScript和HTML之间的交互式通过用户和浏览器操作页面时引发的事件机制来处理的。...

半指温柔乐
2017/11/08
0
0
在 ASP.NET 的 UpdatePanel 中使用 jQuery

简述 我在开发一个 ASP.NET Webforms 应用程序时, 发现 JQuery 会在我同时使用的 UpdatePanel 的时候失效! 在我深入研究后发现,原来是UpdatePanel 的局部刷新事件在调用完成后移除了JQuery ...

oschina
2013/06/04
626
0
jQuery 1.9.1中live()变更

开始的时候在jQuery.1.7.1中使用了.live()觉得很好用,特别是在绑定事件之后再加入的元素的事件绑定上很方便(第一次live之后以后添加的元素就不需要绑定啦) 后来jQuery更新到1.9.1,页面中的...

FuniK
2013/12/20
0
0
jQuery中.live()方法的使用方法

jQuery中.live()方法的使用方法 live(type, [data], fn) 概述 jQuery 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。 这个方法是基本是的 .bind() 方法的一...

风子
2012/09/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 白掌柜说了卖货不卖身

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @爱漫爱 :这是一场修行分享羽肿的单曲《Moony》 手机党少年们想听歌,请使劲儿戳(这里) @clouddyy :开不开心? 开心呀, 我又不爱睡懒觉…...

小小编辑
今天
8
0
大数据教程(11.7)hadoop2.9.1平台上仓库工具hive1.2.2搭建

上一篇文章介绍了hive2.3.4的搭建,然而这个版本已经不能稳定的支持mapreduce程序。本篇博主将分享hive1.2.2工具搭建全过程。先说明:本节就直接在上一节的hadoop环境中搭建了! 一、下载apa...

em_aaron
今天
2
0
开始看《JSP&Servlet学习笔记》

1:WEB应用简介。其中1.2.1对Web容器的工作流程写得不错 2:编写Servlet。搞清楚了Java的Web目录结构,以及Web.xml的一些配置作用。特别是讲了@WebServlet标签 3:请求与响应。更细致的讲了从...

max佩恩
今天
4
0
mysql分区功能详细介绍,以及实例

一,什么是数据库分区 前段时间写过一篇关于mysql分表的的文章,下面来说一下什么是数据库分区,以mysql为例。mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可...

吴伟祥
今天
3
0
SQL语句查询

1.1 排序 通过order by语句,可以将查询出的结果进行排序。放置在select语句的最后。 格式: SELECT * FROM 表名 ORDER BY 排序字段ASC|DESC; ASC 升序 (默认) DESC 降序 1.查询所有商品信息,...

stars永恒
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部