浅谈 jQuery 事件源码定位问题


Posted in Javascript onJune 18, 2014

昨天群里有人问了个事件源码定位的问题,简单描述下是这样的。

在一个不是自己写的页面上,如何快速定位到他绑定的事件代码在哪?(页面用的是jQuery)
这个问题,说难不难,说简单也没那么简单,万一用的是委托之类也会麻烦点。

在 chrome 的控制台里有个 Event Listeners,这里会显示你所选择元素的事件,如果是原生事件,他会直接显示,
你点击一下事件就会跳到对应代码里了,可是 jQuery 绑定的事件却不是这样的,你点击后只会跳到 jQuery 源码里,
min后的jQuery源码密密麻麻的,看着都眼花。

浅谈 jQuery 事件源码定位问题

浅谈 jQuery 事件源码定位问题

关于jQuery对于事件的管理,大牛们也分析的非常透彻了,我就不??铝耍?蛭?皇俏颐墙裉煲?档闹氐恪?br /> 我们要说的重点是怎么定位到事件源码处。因为jQuery版本众多,而且重构过多次,所以要分情况来说了。

基本上 1.2.6-1.8 和 1.9 两种情况,经过测试,大体上定为下面2个版本
1.2.6-1.8 用  $.data( elem, "events", undefined, true ); 
1.9+ 用  $._data( elem, "events" ); 

PS: 你现在也可以按 F12 打开控制台看看结果,当然也可以复制下面的源码自己测试。
由于谷歌被墙的厉害,所以把cdn换成百度的了。2014-06-07

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>test</title>
  <script src="http://libs.baidu.com/jquery/1.4.0/jquery.js"></script>
</head>

<body>
  <input type="button" id="testbtn" value="testbtn" />
  <script>
    var version = ["1.2.6", "1.3.0", "1.4.0", "1.5.0", "1.6.0", "1.7.0", "1.8.0", "1.9.0", "1.10.0"],
      elem = $("#testbtn")[0], // 待操作的元素
      url, // jquery 地址
      jq = null, // 保存新的jquery句柄
      jqver, // jqury 版本
      fn; // 函数句柄

    for (var i = 0; i < version.length; i++) {
      url = "http://libs.baidu.com/jquery/" + version[i] + "/jquery.min.js";

      $.getScript(url, function() {
        jq = $.noConflict(true); // 释放控制权
        jqver = jq.fn.jquery; // 当前 jquery 版本
        fn = new Function('ver_' + jqver.replace(/\./g, "_"), ''); // 生成类似 function (ver_1_9_0) {} 这样的函数
        jq(elem).click(fn).click(fn).bind("test", fn); // 普通事件和自定义事件

        console.log(
          jqver,
          jq.data && jq.data(elem, "events", undefined, true),
          jq._data && jq._data(elem, "events")
        );
      });
    }
  </script>
</body>
</html>

如果不出意外,你可以在控制台看到这样的显示结果
浅谈 jQuery 事件源码定位问题

展开后可以看到绑定的函数参数里的版本和当前版本是对应的。
浅谈 jQuery 事件源码定位问题

 

可以看到
1.2.6-1.4 只支持  $.data( elem, "events", undefined, true ); 
1.5-1.8 两者都支持
1.9-1.11 只支持  $._data( elem, "events" ); 

那么我们可以写个函数简单的兼容下,然他全兼容即可

function lookEvents (elem) {
  return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );
}

现在调用 lookEvents 就可以得到对应的 events 对象了。

虽然可以看到了我们绑定的自定义事件,但还是不知道他在哪个文件哪一行啊。

下面我们就来定位他的具体位置,我们就拿 1.7 的试试。
PS: 下面操作都是在控制台完成,我的环境是 chrome 34

function lookEvents (elem) {
  return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );
}
var event = lookEvents($("#testbtn")[0]); // 获取绑定的事件
event.click[0].handler // 获取click事件的第一个事件源码地址

复制到控制台,按回车运行后,不出意外可以看到下面这个结果。

浅谈 jQuery 事件源码定位问题

有没有看到右下角的 1.html:36 这个就是源码所在的文件和对应的行号了。
你可以直接点击 1.html:36 跳到对应的代码处,是不是觉得很给力啊。

浅谈 jQuery 事件源码定位问题

上面方法适用于 1.5+ 版本的 jQuery,对于 1.2.6-1.4 的版本,稍微有点不同,不过也非常简单。

function lookEvents (elem) { return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );}var event = lookEvents($("#testbtn")[0]); // 获取绑定的事件event.click; // 查看有几个click事件,如果要查看其他事件直接输入 event 然后回车即可

上面看到的编码就是对应事件句柄了,比如我这的 1,2 事件(如下图显示), 这个编号不是按顺序的,这个要注意。
 event.click[1] // 获取click事件的 id是1 的事件源码地址 
不出意外可以看到下面这个结果。

浅谈 jQuery 事件源码定位问题

从操作来说,不管是 1.2.6-1.4 还是 1.5+ 版本 都差不多,只是 1.5+ 利用数组模式管理函数句柄了,比较方便。
好了,该说的都说完了,小伙伴们各种测试起来吧。

Javascript 相关文章推荐
Jquery中的CheckBox、RadioButton、DropDownList的取值赋值实现代码
Oct 12 Javascript
简单对比分析JavaScript中的apply,call与this的使用
Dec 04 Javascript
基于jQuery1.9版本如何判断浏览器版本类型
Jan 12 Javascript
vue.js入门教程之计算属性
Sep 01 Javascript
jquery 多个radio的click事件实例
Dec 03 Javascript
微信小程序 开发经验整理
Feb 15 Javascript
js 性能优化之算法和流程控制
Feb 15 Javascript
js实现适配不同的屏幕大小
Apr 10 Javascript
详解vue项目打包后通过百度的BAE发布到网上的流程
Mar 05 Javascript
Vue filter介绍及详细使用
Apr 04 Javascript
如何在微信小程序里面退出小程序的方法
Apr 28 Javascript
判断js数据类型的函数实例详解
May 23 Javascript
js调试系列 源码定位与调试[基础篇]
Jun 18 #Javascript
js调试系列 控制台命令行API使用方法
Jun 18 #Javascript
js调试系列 初识控制台
Jun 18 #Javascript
ext前台接收action传过来的json数据示例
Jun 17 #Javascript
Ext GridPanel加载完数据后进行操作示例代码
Jun 17 #Javascript
ext中store.load跟store.reload的区别示例介绍
Jun 17 #Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
Jun 17 #Javascript
You might like
回首过去10年中最搞笑的10部动漫,哪一部让你节操尽碎?
2020/03/03 日漫
PHP file_get_contents设置超时处理方法
2013/09/30 PHP
php判断IP地址是否在多个IP段内
2020/08/18 PHP
js弹出模式对话框,并接收回传值的方法
2013/03/12 Javascript
jQuery Ajax调用WCF服务详细教程
2015/03/31 Javascript
node.js cookie-parser 中间件介绍
2016/06/06 Javascript
JavaScript第一篇之实现按钮全选、功能
2016/08/21 Javascript
MUI  Scroll插件的使用详解
2017/04/13 Javascript
BootStrap中的Fontawesome 图标
2017/05/25 Javascript
微信小程序中使用Promise进行异步流程处理的实例详解
2017/08/17 Javascript
Vue 2.5 Level E 发布了: 新功能特性一览
2017/10/24 Javascript
vue如何将v-for中的表格导出来
2018/05/07 Javascript
Vue+Element UI+Lumen实现通用表格分页功能
2019/02/02 Javascript
vue项目中运用webpack动态配置打包多种环境域名的方法
2019/06/24 Javascript
vue如何使用async、await实现同步请求
2019/12/09 Javascript
12 种使用Vue 的最佳做法
2020/03/30 Javascript
js+css实现扇形导航效果
2020/08/18 Javascript
python计算时间差的方法
2015/05/20 Python
举例讲解Python中的Null模式与桥接模式编程
2016/02/02 Python
Python中将字典转换为列表的方法
2016/09/21 Python
python分批定量读取文件内容,输出到不同文件中的方法
2018/12/08 Python
python实现AES加密与解密
2019/03/28 Python
python绘制雪景图
2019/12/16 Python
使用PyOpenGL绘制三维坐标系实例
2019/12/24 Python
基于python实现模拟数据结构模型
2020/06/12 Python
python中可以声明变量类型吗
2020/06/18 Python
加拿大花店:1800Flowers.ca
2016/11/16 全球购物
Spartoo荷兰:鞋子、包包和服装
2018/07/12 全球购物
澳大利亚百货商店中销量第一的商务衬衫品牌:Van Heusen
2018/07/26 全球购物
ToysRus日本官网:玩具反斗城
2018/09/08 全球购物
土木工程师岗位职责
2013/11/24 职场文书
教师岗位聘任书范文
2014/03/29 职场文书
公司试用期员工自我评价
2014/09/17 职场文书
幼儿园综治宣传月活动总结
2015/05/07 职场文书
python文本处理的方案(结巴分词并去除符号)
2021/05/26 Python
Vue2项目中对百度地图的封装使用详解
2022/06/16 Vue.js