文档章节

jquery事件绑定丢失

cyper
 cyper
发布于 2015/12/01 22:27
字数 697
阅读 72
收藏 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
码字总数 143329
作品 0
武汉
前端工程师
私信 提问
jQuery基础 - 常用基本属性

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

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

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

半指温柔乐
2017/11/08
0
0
javascript中查看元素事件函数的一些技巧

在分析一些网页的时候,经常会发现点击某个按钮会触发某个动作,当页面比较复杂,包含的js文件又多,这时候要找到这段触发函数的代码写在哪里就比较困难。比如,在某个html页面中,发现如下一...

技术小甜
2017/11/07
0
0
jquery中对动态生成的标签不会响应click事件

Jquery中对ajax动态生成的html标签不会响应 $(selector).click(function.. 或者$(selector).bind('click',function.., 需要用.live jQuery 1.7 开始,不再建议使用 .live() 方法。请使用 .o...

LiShixi
2011/09/03
0
3
jQuery的事件处理方法介绍 - bind(),live(),delegate(),on()

在 jQuery的开发过程中,我们往往需要处理各种事件,例如,click(),hover()等。在jQuery的API中,我们可以使用不同的方法来将 这些事件绑定到特定的元素中。今天这篇文章中,我们将要介绍如...

kisshua
2012/04/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用 React 和 Vue 创建相同的应用,他们有什么差异?

在工作中应用 Vue 之后,我对它有了相当深刻的理解。 不过,俗话说「外国的月亮比较圆」,我好奇「外国的」 React 是怎么样的。 我阅读了 React 文档并观看了一些教程视频,虽然它们很棒,但...

阿K1225
8分钟前
0
0
如何使用Kubernetes的configmap通过环境变量注入到pod里

在Kubernetes官网里,有这样一篇文章,提到了Kubernetes里的一个最佳实践就是把应用代码同配置信息分开,一种方式就是使用Kubernetes 1.2里引入的configmap概念。 https://kubernetes.io/bl...

JerryWang_SAP
24分钟前
0
0
2天闭门培训|以太坊智能合约从入门到实战(北京)

2天培训 16个课时 探寻技术原理,精通以太坊智能合约开发 以太坊智能合约是现在应用的最广泛的区块链应用开发方式,HiBlock区块链社区针对以太坊智能合约的学习特别推出2天闭门研修班,通过2...

HiBlock
26分钟前
0
0
限定某个目录禁止解析php,限制user_agent,php相关配置

11月20日任务 11.28 限定某个目录禁止解析php 11.29 限制user_agent 11.30/11.31 php相关配置 1.限定某个目录禁止解析php 核心配置文件内容 <Directory /data/wwwroot/www.123.com/upload> p...

hhpuppy
37分钟前
2
0
Spring的好文章

孤傲苍狼 https://www.cnblogs.com/xdp-gacl/p/4249939.html 跟我学spring http://jinnianshilongnian.iteye.com/blog/1413846 SpringIoc 和Spring Aop 代理模式: 静态代理 动态代理 cglib代......

wangwei2134
49分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部