从一个bug说jquery的事件注册和触发机制
来源:互联网 发布:易语言硬件断点源码 编辑:程序博客网 时间:2024/06/06 07:31
问题描述
同一域名下有两个页面parent.html,child.html。parent.html中通过iframe嵌入child.html。父页面触发自定义事件,子页面对其进行响应。
两页面代码如下:
1.parent.html
<body> 我是父页面 <iframe></iframe> <script src="/js/jquery.min.js"></script> <script> $("iframe").attr('src', 'child.html'); /*0.5s后触发自定义事件myevent*/ setTimeout(function(){ $(document).trigger('myevent'); }, 500); </script></body>
2.child.html
<body> 我是子页面 <script src="/js/jquery.min.js"></script> <script> /*响应父页面myevent*/ $(parent.document).bind("myevent",function(){ console.log('i get it') }) </script></body>
运行后,并没有在控制台输出”i get it”。也就是说子页面未能响应父页面的trigger(‘myevent’)。
分析
猜测了几个原因未果后,决定还是看下源码找问题。
- bind方法对应jQuery.event.add。
- trigger方法应jQuery.event.trigger,并最终落实到jQuery.event.handle执行。
我们来看看这两个方法吧(只摘说明问题需要的代码)
jQuery.event = { /* * elem:dom元素 * types:事件 * handler:处理函数 */ add : function(elem, types, handler, data){ /*给处理函数指定唯一id*/ handler.guid = this.guid++; /*从缓存中取出已有处理函数*/ events = jQuery.data(elem, "events"); handlers = events[type]; /*以唯一id为key,存入新的处理函。*/ handlers[handler.guid] = handler; }, handle : function(event){ /*取出dom元素上的所的事件处理函数, 顺次执行*/ handlers = (jQuery.data(this, "events") || {})[event.type]; for (var j in handlers){ ... } }}
两个方法均使用到了jQuery.data, 此函数只是拿来作缓存之用,所有数据存到了jQuery.cache。cache就是jQuery的一个内部变量,被初始化为{}。
jQuery.extend({ cache: {}, data: function(elem, name, data) { jQuery.cache[id][name] = data; }})
注:以上代码摘自jquery-1.2.6版本,新版本代码要复杂一些,但实现机制类似。
至此,我们可以总结jQuery的事件注册/触发机制如下:
- 对元素进行事件绑定(bind/on)时,事件会以elem->handles的kv对记录在内部缓存jQuery.cache中。
- 触发事件时,从cache中查找该元素对应的所有事件,依次执行。
bug原因
从以上分析不难看出,导致我们bug的原因如下:
- 子页面的jQuery和父页面的jQuery是功能相同的两个不同对象。就像双胞胎,外表一致,内里却不尽相同。
- 子页面的myevent处理函数保存在了子页面的jQury.cache中
- 父页面的jQury.cache上没有myevent处理函数,触发时当然也不会有调用。
在jQuery内部代码的add和trigger中加log也可以看出这一点
解决
将child.html中的js代码改为
parent.$(parent.document).bind("myevent",function(){ console.log('i get it') });
如此一来,父子页面的事件触发,子页面的事件响应作用在了父页面的jQuery.cache上,问题得以解决。
- 从一个bug说jquery的事件注册和触发机制
- 从一个bug说jquery中的attr和prop
- 事件的触发机制,定义,注册
- jquery事件触发 兼容性BUG
- JQuery注册触发自定义事件
- IE9的一个BUG:propertychange和input事件在拖拽 / 剪切 / 删除时无法触发
- PB事件/函数的触发机制和触发方式
- PB事件/函数的触发机制和触发方式
- PB事件/函数的触发机制和触发方式
- PB事件/函数的触发机制和触发方式
- Linux 下notifier chain 机制的注册和触发讲解
- WebSocket的事件触发机制
- jQuery 中事件的触发
- JQuery触发事件的方法
- 多次注册事件会导致一个事件被触发多次
- jquery绑定click事件,在ios7 8下不触发的bug
- jQuery事件触发和js手动触发事件
- jQuery基础教程之如何注册以及触发自定义事件
- MySQL创建事件启动事件停止事件
- 51nod-【1108 距离之和最小 V2】
- mac系统设置目录权限
- Android 如何确定camera呈像方向
- Android压缩图片到100K以下并保持不失真的高效方法
- 从一个bug说jquery的事件注册和触发机制
- android开发之百度统计
- android上传文件到服务器(图片、文本等)
- [LeetCode]Merge Sorted Array
- 441. Arranging Coins
- HighQualityAudio-FFMPEG
- Android"挂逼"修炼之行---微信摇骰子和猜拳作弊器原理解析
- typecho极验验证插件
- mysql 存储过程,执行结果"Error Code: 1329. No data - zero rows fetched, selected, or processed"