浅谈 jQuery 事件源码定位问题

原文:浅谈 jQuery
事件源码定位问题

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

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

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

关于jQuery对于事件的管理,大牛们也分析的非常透彻了,我就不啰嗦了,因为不是我们今天要说的重点。
我们要说的重点是怎么定位到事件源码处。因为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
打开控制台看看结果,当然也可以复制下面的源码自己测试。


<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script src="http://ajax.googleapis.com/ajax/libs/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", "1.11.0"],
elem = $("#testbtn")[0], // 待操作的元素
url, // jquery 地址
jq = null, // 保存新的jquery句柄
jqver, // jqury 版本
fn; // 函数句柄

for (var i=0; i<version.length; i++) {
url = "http://ajax.googleapis.com/ajax/libs/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>

如果不出意外,你可以在控制台看到这样的显示结果

展开后可以看到绑定的函数参数里的版本和当前版本是对应的。

可以看到
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事件的第一个事件源码地址

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

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

上面方法适用于 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 的事件源码地址 
不出意外可以看到下面这个结果。

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

浅谈 jQuery 事件源码定位问题

时间: 2024-10-30 12:12:56

浅谈 jQuery 事件源码定位问题的相关文章

浅谈jquery关于select框的取值和赋值

浅谈jquery关于select框的取值和赋值 jQuery("#select_id").change(function(){}); // 1.为Select添加事件,当选择其中一项时触发 var checkValue = jQuery("#select_id").val(); // 2.获取Select选中项的Value var checkText = jQuery("#select_id :selected").text(); // 3.获取

由莫名其妙的错误开始---浅谈jquery的dom节点创建

有一个字符串是这样的:var s = '<html lang="en" class="js no-touch discourse-no-touch">'+ '<head><meta name="csrf-token" content="Oul7WqVh4FBVse2yGeY8ZkqoN5/9/2ImxohJvUYEJYc="/></head><body></bo

浅谈jquery选择器

首先来说说jquery选择器的优势: 1.简洁的写法  2.支持css1.0到3.0选择器 3.完善的处理机制. 再来说说分类: jquery选择器分为基本选择器.层次选择器.属性选择器.基本过滤选择器.可见性过滤选择器. 基本选择器分为:标签选择器.类选择器.ID选择器.并集选择器.交集选择器.全局选择器. 常用的就两种:类选择器和ID选择器. 类选择器直接写给定的标签名就可以了,例如:$("h2").css("background","red"

浅谈jquery中prop()和attr()

我们都知道,一般在jquery中设置属性时要用到attr()方法,现在我们有一个效果,点击按钮切换复选框的选中状态,下面贴出html代码: <input type="checkbox" id="check"> <label>复选框</label> <input type="button" value="切换" id="btn"> js代码: <scrip

浅谈jQuery中 wrap() wrapAll() 与 wrapInner()的差异

本文结合W3School的文档,分析了jQuery中 wrap() wrapAll() 与 wrapInner()的差异,并给出了图文对比教程,非常的简单实用,有需要的朋友可以参考下 今晚看书的时候发现jQuery有三个包裹节点的方法,百度了一下jQuery wrap() / wrapAll() / wrapInner(),果然搜索结果 W3School的文档说明是排第一的. 可是,W3School的解释是这样的: jQuery 文档操作 - wrap() 方法 wrap() 方法把每个被选元素

浅谈jquery事件命名空间

什么是jquery的事件命名空间? 先看如下简单代码: $("#btn").on("click.name1.name2",function(){ console.log(1); }) 其中name1.name2即为所绑定click事件的命名空间,在这里命名空间在事件名后面用"."来连接.在这里也可以把命名空间理解为别名,即这里绑定的click事件有两个别名name1和name2. 绑定具有命名空间的事件如何解除绑定? 如下8种写法均可取消绑定之前

浅谈jquery中的ajax请求和跨域请求

ajax请求数据的代码: $(function () { $.ajax({ url:url,//请求文件所在的url type:"get",//请求的方式 success:function (data) { console.log(data);//返回的数据 } })})这样请求来的数据一般情况下都可以使用,但是有时候在从这个域名到另外一个域名请求数据时往往会出现所谓的跨域请求问题, 浏览器均默认开启了同源策略,它指Ajax请求所在的页面和被请求的页面在协议.域名.端口均相同才能被访问

浅谈RxJava源码解析(观察者),创建(create、from、just),变换(Map、flatMap)、线程调度

一.创建操作: 1.观察者模式:RxJava的世界里,我们有四种角色: Observable<T>(被观察者).Observer(观察者) Subscriber(订阅者).Subject Observable和Subject是两个"生产"实体,Observer和Subscriber是两个"消费"实体.Observable 和 Observer 通过 subscribe() 方法实现订阅关系,从而 Observable 可以在需要的时候发出事件来通知 Ob

浅谈Jquery中的bind(),live(),delegate(),on()绑定事件方式

前言 因为项目中经常会有利用jquery操作dom元素的增删操作,所以会涉及到dom元素的绑定事件方式,简单的归纳一下bind,live,delegate,on的区别,以便以后查阅,也希望该文章日后能帮助到园友,文中如有不当之处,还望各位指正,话不多说,直接进入正题. bind() 简要描述 bind()向匹配元素添加一个或多个事件处理器. 使用方式 $(selector).bind(event,data,function) event:必需项:添加到元素的一个或多个事件,例如 click,db