浅谈 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中Ajax 缓存带来的影响的解决方法
May 19 Javascript
JS打印gridview实现原理及代码
Feb 05 Javascript
JS+CSS制作DIV层可(最小化/拖拽/排序)功能实现代码
Feb 25 Javascript
iframe窗口高度自适应的实现方法
Jan 08 Javascript
js实现网页标题栏闪烁提示效果实例分析
Nov 20 Javascript
jQuery on()方法示例及jquery on()方法的优点
Aug 27 Javascript
限制文本框只能输入数字||只能是数字和小数点||只能是整数和浮点数
May 27 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
Javascript摸拟自由落体与上抛运动原理与实现方法详解
Apr 08 Javascript
Vue 3.0 全家桶抢先体验
Apr 28 Javascript
在Echarts图中给坐标轴加一个标识线markLine
Jul 20 Javascript
JS中一些高效的魔法运算符总结
May 06 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
Codeigniter生成Excel文档的简单方法
2014/06/12 PHP
PHP中strlen()和mb_strlen()的区别浅析
2014/06/19 PHP
CodeIgniter钩子用法实例详解
2016/01/20 PHP
php实现商城购物车的思路和源码分析
2020/07/23 PHP
JS控件的生命周期介绍
2012/10/22 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
JavaScript实现点击自动选择TextArea文本的方法
2015/07/02 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
深入学习jQuery Validate表单验证
2016/01/18 Javascript
浅谈javascript基础之客户端事件驱动
2016/06/10 Javascript
vue router动态路由下让每个子路由都是独立组件的解决方案
2018/04/24 Javascript
vue.js实现数据库的JSON数据输出渲染到html页面功能示例
2019/08/03 Javascript
vue实现axios图片上传功能
2019/08/20 Javascript
Node.js控制台彩色输出的方法与原理实例详解
2019/12/01 Javascript
JS实现纵向轮播图(初级版)
2020/01/18 Javascript
JavaScript实现tab栏切换效果
2020/03/16 Javascript
vue实现简单跑马灯效果
2020/05/25 Javascript
Vue两种组件类型:递归组件和动态组件的用法
2020/08/06 Javascript
请求时token过期自动刷新token操作
2020/09/11 Javascript
vue项目打包后请求地址错误/打包后跨域操作
2020/11/04 Javascript
Python素数检测实例分析
2015/06/15 Python
python 字典 按key值大小 倒序取值的实例
2018/07/06 Python
pip install python 快速安装模块的教程图解
2019/10/08 Python
pycharm通过anaconda安装pyqt5的教程
2020/03/24 Python
python 无损批量压缩图片(支持保留图片信息)的示例
2020/09/22 Python
css3过渡_动力节点Java学院整理
2017/07/11 HTML / CSS
美国在线咖啡、茶和餐厅供应商:LollicupStore
2018/05/04 全球购物
Oracle的内存结构(Memory structures)
2015/06/10 面试题
下面代码从性能上考虑,有什么问题
2015/04/03 面试题
总经理秘书的岗位职责
2013/12/27 职场文书
写给女生的道歉信
2014/01/08 职场文书
构建高效课堂实施方案
2014/03/13 职场文书
2015年高一班主任工作总结
2015/05/13 职场文书
培养联系人考察意见
2015/06/01 职场文书
OpenCV 图像梯度的实现方法
2021/07/25 Python
python使用shell脚本创建kafka连接器
2022/04/29 Python