当前位置: 首页 > 编程日记 > 正文

jQuery事件处理一瞥

以前部门一直都是使用一个名为QTT的JS框架。最近老大提出要转用jQuery框架,需要将旧框架的一些JQ没有实现的功能移植到JQ中去。当我移植到event库的时候,以下是其代码:

QTT.event = {KEYS : {BACKSPACE : 8,TAB : 9,RETURN : 13,ESC : 27,SPACE : 32,LEFT : 37,UP : 38,RIGHT : 39,DOWN : 40,DELETE : 46},extendType : /(click|mousedown|mouseover|mouseout|mouseup|mousemove|scroll|contextmenu|resize)/i,_eventListDictionary : {},_fnSeqUID : 0,_objSeqUID : 0,addEvent : function(obj, eventType, fn, argArray) {var cfn = fn,res = false, l;if (!obj) {return res;}if (!obj.eventsListUID) {obj.eventsListUID = "e" + (++QTT.event._objSeqUID);QTT.event._eventListDictionary[obj.eventsListUID] = {};}l = QTT.event._eventListDictionary[obj.eventsListUID];if (!fn.__elUID) {fn.__elUID = "e" + (++QTT.event._fnSeqUID) + obj.eventsListUID;}if (!l[eventType]) {l[eventType] = {};}if(typeof(l[eventType][fn.__elUID])=='function'){return false;}if (QTT.event.extendType.test(eventType)) {var argArray = argArray || [];cfn = function(e) {
//吐槽音:为啥这里不用obj而用了null, 害得我在回调事件中不能用this -_-!!return fn.apply(null, ([QTT.event.getEvent(e)]).concat(argArray));};}if (obj.addEventListener) {obj.addEventListener(eventType, cfn, false);res = true;} else if (obj.attachEvent) {res = obj.attachEvent("on" + eventType, cfn);} else {res = false;}if (res) {l[eventType][fn.__elUID] = cfn;}return res;},removeEvent : function(obj, eventType, fn) {var cfn = fn, res = false, l;if (!obj) {return res;}if (!cfn) {return QTT.event.purgeEvent(obj, eventType);}if (!obj.eventsListUID) {obj.eventsListUID = "e" + (++QTT.event._objSeqUID);QTT.event._eventListDictionary[obj.eventsListUID] = {};}l = QTT.event._eventListDictionary[obj.eventsListUID];if (!fn.__elUID) {fn.__elUID = "e" + (++QTT.event._fnSeqUID) + obj.eventsListUID;}if (!l[eventType]) {l[eventType] = {};}if (QTT.event.extendType.test(eventType)&&l[eventType]&&l[eventType][fn.__elUID]) {cfn = l[eventType][fn.__elUID];}if (obj.removeEventListener) {obj.removeEventListener(eventType, cfn, false);res = true;} else if (obj.detachEvent) {obj.detachEvent("on" + eventType, cfn);res = true;} else {return false;}if (res && l[eventType]) {delete l[eventType][fn.__elUID];}return res;},purgeEvent : function(obj, type) {var l;if (obj.eventsListUID && (l=QTT.event._eventListDictionary[obj.eventsListUID]) && l[type]) {for (var k in l[type]) {if (obj.removeEventListener) {obj.removeEventListener(type, l[type][k],false);} else if (obj.detachEvent) {obj.detachEvent('on' + type, l[type][k]);}}}if (obj['on' + type]) {obj['on' + type] = null;}if (l) {l[type] = null;delete l[type];}return true;},getEvent : function(evt) {var evt = evt || window.event;if (!evt && !QTT.userAgent.ie) {var c = this.getEvent.caller,cnt = 1;while (c) {evt = c.arguments[0];if (evt && Event == evt.constructor) {break;}else if(cnt > 32){break;}c = c.caller;cnt++;}}return evt;},getButton : function(evt) {var e = QTT.event.getEvent(evt);if (!e) {return -1}if (QTT.userAgent.ie) {return e.button - Math.ceil(e.button / 2);} else {return e.button;}},getTarget : function(evt) {var e = QTT.event.getEvent(evt);if (e) {return e.target || e.srcElement;} else {return null;}},getCurrentTarget : function(evt) {var e = QTT.event.getEvent(evt);if (e) { return e.currentTarget || document.activeElement;} else {return null;}},cancelBubble : function(evt) {evt = QTT.event.getEvent(evt);if (!evt) {return false}if (evt.stopPropagation) {evt.stopPropagation();} else {if (!evt.cancelBubble) {evt.cancelBubble = true;}}},preventDefault : function(evt) {evt = QTT.event.getEvent(evt);if (!evt) {return false}if (evt.preventDefault) {evt.preventDefault();} else {evt.returnValue = false;}},mouseX : function(evt) {evt = QTT.event.getEvent(evt);return evt.pageX || (evt.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));},mouseY : function(evt) {evt = QTT.event.getEvent(evt);return evt.pageY || (evt.clientY + (document.documentElement.scrollTop || document.body.scrollTop));},getRelatedTarget: function(ev) {ev = QTT.event.getEvent(ev);var t = ev.relatedTarget;if (!t) {if (ev.type == "mouseout") {t = ev.toElement;} else if (ev.type == "mouseover") {t = ev.fromElement;} else {}}return t;},bind : function(obj, method) {var args = Array.prototype.slice.call(arguments, 2);return function() {var _obj = obj || this;var _args = args.concat(Array.prototype.slice.call(arguments, 0));if (typeof(method) == "string") {if (_obj[method]) {return _obj[method].apply(_obj, _args);}} else {return method.apply(_obj, _args);}}} };

以上方法中,addEvent、removeEvent、purgeEvent、bind这几个方法在JQ中有直接实现的。但好像在JQ的api中并没有跟getEvent、getButton、getTarget、getCurrentTarget、cancelBubble、preventDefault、mouseX、mouseY、getRelatedTarget这几个方法相关的事件。

但是JQ库这么强大,不可能没考虑这些通用函数的。既然API手册没有说,就只能翻出了jQuery的源码来看下了。

我在jQuery.event这个命名空间下发现了这个方法:

fix: function( event ) {if ( event[ expando ] ) {return event;}// store a copy of the original event object// and "clone" to set read-only propertiesvar originalEvent = event;event = jQuery.Event( originalEvent );for ( var i = this.props.length, prop; i; ) {prop = this.props[ --i ];event[ prop ] = originalEvent[ prop ];}// Fix target property, if necessaryif ( !event.target ) {event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either}// check if target is a textnode (safari)if ( event.target.nodeType === 3 ) {event.target = event.target.parentNode;}// Add relatedTarget, if necessaryif ( !event.relatedTarget && event.fromElement ) {event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;}// Calculate pageX/Y if missing and clientX/Y availableif ( event.pageX == null && event.clientX != null ) {var doc = document.documentElement, body = document.body;event.pageX = event.clientX + (doc && doc.scrollLeft||body && body.scrollLeft||0)
               - (doc && doc.clientLeft||body && body.clientLeft||0);event.pageY = event.clientY + (doc && doc.scrollTop||body && body.scrollTop||0)
               - (doc && doc.clientTop||body && body.clientTop||0);}// Add which for key eventsif ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {event.which = event.charCode || event.keyCode;}// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)if ( !event.metaKey && event.ctrlKey ) {event.metaKey = event.ctrlKey;}// Add which for click: 1 === left; 2 === middle; 3 === right// Note: button is not normalized, so don't use itif ( !event.which && event.button !== undefined ) {event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));}return event; },

顿时廓然开朗。从功能上看,jQuery.event.fix() 的功能是修复event对象,让事件在各种浏览器下表现一致。它修复的事件属性包括:

1.event.target          =====>被触发的对象,可替代QTT.event.getTarget()

2.event.relatedTarget                  =====>可替代QTT.event.getRelatedTarget()

3.event.pageX和event.pageY        =====>事件触发时的鼠标位置,可替代QTT.event.mouseX()和QTT.event.mouseY()

4.event.which                             =====>事件触发时的按键,包括键盘和鼠标。可替代QTT.event.getButton()

5.event.metaKey                         =====>事件触发时有没按下ctrl键(Mac下是meta键)

值得注意的是上面的event.which,它既可以用来获得键盘输入,也可以获得鼠标输入。标准的button采用0,1,2表示鼠标的左,中,右键。jQuery的which则使用用1,2,3。

除了对事件属性的修复,它还对最关键的event对象进行了修复:

var originalEvent = event;   event = jQuery.Event( originalEvent );

这个jQuery.Event的代码如下:

jQuery.Event = function( src ) {// Allow instantiation without the 'new' keywordif ( !this.preventDefault ) {return new jQuery.Event( src );}// Event objectif ( src && src.type ) {this.originalEvent = src;this.type = src.type;// Event type} else {this.type = src;}// timeStamp is buggy for some events on Firefox(#3843)// So we won't rely on the native valuethis.timeStamp = now();// Mark it as fixedthis[ expando ] = true;
};jQuery.Event.prototype = {preventDefault: function() {this.isDefaultPrevented = returnTrue;var e = this.originalEvent;if ( !e ) {return;}// if preventDefault exists run it on the original eventif ( e.preventDefault ) {e.preventDefault();}// otherwise set the returnValue property of the original event to false (IE)e.returnValue = false;},stopPropagation: function() {this.isPropagationStopped = returnTrue;var e = this.originalEvent;if ( !e ) {return;}// if stopPropagation exists run it on the original eventif ( e.stopPropagation ) {e.stopPropagation();}// otherwise set the cancelBubble property of the original event to true (IE)e.cancelBubble = true;},stopImmediatePropagation: function() {this.isImmediatePropagationStopped = returnTrue;this.stopPropagation();},isDefaultPrevented: returnFalse,isPropagationStopped: returnFalse,isImmediatePropagationStopped: returnFalse
};

可见经过处理后,event对象就拥有stopPropagation和preventDefault两个方法,可替代QTT.event.cancelBubble()和QTT.event.preventDefault()。

并且不需要通过QTT.event.getEvent()这样的方式去获取event对象了。

于是如果你需要在事件回调函数中阻止冒泡或者默认事件的话,这样写即可:

1.event.stopPropagation();
事件处理过程中,阻止了事件冒泡,但不会阻击默认行为(例如超链接的跳转)

2.return false;
事件处理过程中,阻止了事件冒泡,并且也阻止了默认行为

3.event.preventDefault();
事件处理过程中,不阻击事件冒泡,但阻击默认行为

还有一点,就是getEvent这个函数是干什么用的呢?先看一下其定义:

getEvent : function(evt) {var evt = evt || window.event;if (!evt && !QTT.userAgent.ie) {var c = this.getEvent.caller,cnt = 1;while (c) {evt = c.arguments[0];if (evt && Event == evt.constructor) {break;}else if(cnt > 32){break;}c = c.caller;cnt++;}}return evt;},

本来没看懂的,后来看了这篇文章后明白了。

例如<button οnclick="go(event)">click</button>假如函数写成go(),那FF这些浏览器就无法获取到event对象。这时就得通过caller调用父层函数的参数来获得event对象了。

经过一番分析挖掘之后,QTT.event类就只剩下QTT.event.KEYS和QTT.event.getCurrentTarget是需要移植的了。前者是一些常量,直接移植即可。而这个getCurrentTarget到底是什么呢?再往回翻代码看:

getCurrentTarget : function(evt) {var e = QTT.event.getEvent(evt);if (e) {	return  e.currentTarget || document.activeElement;} else {return null;}
}

部门的前辈对这个函数的解释是“返回获得焦点的对象”,跟target有什么不同呢?

在jQuery中搜索activeElement,没有;搜索currentTarget,发现在这几个方法中有用到:

jQuery.event.trigger
jQuery.event.handle
liveHandler

JQ没有将其单独成一个方法。暂时写到这里,等以后有时间再慢慢研究这个currentTarget。

转载于:https://www.cnblogs.com/lefeng/archive/2012/05/13/2497971.html

相关文章:

【C++】零散知识

1、抛异常时&#xff0c;还会执行析构操作吗&#xff1f; 发生异常&#xff08;抛异常&#xff09;时&#xff0c;在该作用域中的局部非PAD变量&#xff08;即&#xff0c;有构造函数和析构函数的变量&#xff09;会执行析构操作。 2、new出的内存一定在堆上吗&#xff1f; …

百度景鲲“升职记”

整理 | 琥珀出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;近日&#xff0c;据多家媒体报道&#xff0c;百度人力资源负责人崔珊珊发出晋升邮件宣布&#xff0c;智能生活事业群总经理景鲲晋升为副总裁。百度在晋升邮件中评价他&#xff1a;“敢打硬仗、能…

南通市公积金信息系统goldengate复制软件采购

&#xff08;二&#xff09;容灾软件部分&#xff1a;2套Oracle GoldenGate 11G ,1 CPU&#xff08;必须提供原厂商针对本项目授权、质保承诺&#xff09;。特性指标系统平台支持1. 支持主流操作系统&#xff0c;包括&#xff1a;IBM AIX、HP-UX、Linux、Sun Solaris、Mic…

开源需自立!Android、GitHub、Apache全线告急!

作者 | 胡巍巍&伍杏玲责编 | 唐小引出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;华为四面楚歌&#xff0c;“破窗效应”爆发&#xff01;继5月16日美国商务部工业与安全局&#xff08;BIS&#xff09;将华为列入“实体清单”之后&#xff0c;越来越多的美国…

【C】linux下切换工作目录至程序所在目录

1、获取当前程序的绝对路径 /proc/self/exe是一个符号链接&#xff0c;代表当前程序的绝对路径 用readlink读取/proc/self/exe可以获取当前程序的绝对路径 2、从字符串中获取目录 char dirname(char path); 3、改变当前工作目录 int chdir(const char *path ); 4、完整示…

Eclipse基金会发布Eclipse Photon IDE

Eclipse基金会发布了最新版本的Eclipse IDE。Eclipse Photon带来对Java 10和Java EE 8的支持&#xff0c;增强了PHP开发工具和Dark主题等功能。\\Eclipse Java开发工具&#xff08;Eclipse Java Development Tools&#xff0c;JDT&#xff09;对Java 10提供了完整的支持&#x…

【C++】智能指针(一)入门

1、 智能指针背后的设计思想 智能指针背后的思想是RAII&#xff0c;参见博客【C】零散知识 我们先来看一个简单的例子&#xff1a; void remodel(std::string & str) {std::string * ptr new std::string(str);...if (weird_thing())throw exception();str *ptr; dele…

Oracle 11g Release 1 (11.1) PL/SQL_多维 Collection 类型和其异常

本文内容 多维 Collection Collection 异常 多维 Collection 虽然 collection 只有一维的&#xff0c;但可以模型一个多维的。创建一个 collection&#xff0c;其每个元素也是 collection 。例如&#xff0c;创建一个 varray 的 nested table&#xff0c;一个 varray 的 varray…

入门系列之使用fail2ban防御SSH服务器的暴力破解攻击

欢迎大家前往腾讯云社区&#xff0c;获取更多腾讯海量技术实践干货哦~ 本文由SQL GM 发表于云社区专栏 介绍 对于SSH服务的常见的攻击就是暴力破解攻击——远程攻击者通过不同的密码来无限次地进行登录尝试。当然SSH可以设置使用非密码验证验证方式来对抗这种攻击&#xff0c;例…

谁能解答我对知识图谱的上百个疑问?

近日&#xff0c;我们采访了东南大学认知智能研究所所长漆桂林教授和复旦大学知识工场实验室负责人肖仰华教授&#xff0c;围绕知识图谱这两年在研究与产业应用道路上的一些进展与仍面临的问题。漆桂林教授提到&#xff0c;近两年&#xff0c;知识图谱的研究在四大关键技术上都…

ecshop 商品颜色尺寸仿淘宝选择功能教程(2.7.0版本)

牵涉到的修改文件(default模板为例) /themes/default/style.css /themes/default/goods.dwt 注:此路径待修改模板路径.修改步骤:一:控制样式 1.打开/themes/ecshop/p_w_picpaths 加添图片test.gif. 2.打开/themes/ecshop/style.css 最下面添加: /*--------------颜色选择器CSS添…

【C++】Effective STL:50条有效使用STL的经验

第一条&#xff1a;慎重选择容器类型 1、C容器&#xff1a;先混个眼熟 序列容器&#xff1a;array、vector、string、deque、list、forward_list 有序关联容器&#xff1a;set、map、multiset、multimap 无序关联容器&#xff1a;unordered_set、unordered_map、unordered_mu…

ICML 2019接受论文:清华、北大领跑,谷歌强压枝头,BAT略显“低调”

整理 | 刘畅责编 | Jane、Rachel出品 | AI科技大本营&#xff08;id&#xff1a;rgznai100&#xff09;【AI科技大本营导语】今年 6 月&#xff0c;机器学习领域顶会 ICML 2019 将在美国举行。为了帮助大家更好了解会议论文的情况&#xff0c;博世&#xff08;Bosch&#xff09…

C++STL 优先队列priority_queue使用

头文件&#xff1a;#include <queue> 一.申明方式 std::priority_queue<T> q; std::priority_queue<T, std::vector<T>, cmp> q;1.普通方法&#xff1a; priority_queue<int> q; //大的优先级高 priority_queue<int,vector<int>, …

【SVN】linux下svn命令参数详解(二)

svn全部子命令详解1、svn help2、svn add3、svn blame4、svn cat5、svn changelist6、svn checkout7、svn cleanup8、svn commit9、svn copy10、svn delete11、svn diff12、svn export13、svn help14、svn import15、svn info16、svn list17、svn lock18、svn log19、svn merge…

VClient 无法连接Vcenter

前一段在一台windows server 2008 R2上使用local Administrator 安装了VCenter 4.1. 一开始使用VClient 是可以登录的&#xff0c;但是重新启动这台安装有VCenter 的Server 之后就连接不到了。为什么呢&#xff1f; 打开这台Windows Server 2008 查看服务发现SQL 和 VM 都有服务…

智能音箱玩出新花样?这家公司推出2699元的智能虚拟机器人

家居控制、备忘提醒、媒体播放、智能聊天… …如今&#xff0c;AI 应用备受瞩目&#xff0c;智能虚拟机器人也成为了 AI 应用的新方向。 5 月 20 日下午&#xff0c;专注于虚拟机器人研发、平台软件开发运用及销售为一体的公司欧博思发布了 AI BOX 智能虚拟机器人产品。 乍一…

干货 :数据可视化的10个关键术语

2019独角兽企业重金招聘Python工程师标准>>> Format 交互方式 交互式可视化允许您修改&#xff0c;操作和探索计算机显示的数据。绝大多数交互式可视化系统在计算机网络上&#xff0c;但越来越多出现在平板电脑和智能手机上。相比之下&#xff0c;静态可视化只显示单…

【设计模式】三大类:创建型模式、结构型模式、行为型模式

1 创建型模式 本人理解&#xff1a;以C为例&#xff0c;创建对象时&#xff0c;用关键字new来创建&#xff08;实例化&#xff09;对象。用一个函数或类将new的过程封装起来&#xff0c;就是创建型模式。 《设计模式》中的描述&#xff1a; 创建型模式抽象了实例化过程。它们…

单机训练速度提升高达640倍,快手开发GPU广告模型训练平台

作者&#xff5c;廉相如&#xff08;快手FeDA智能决策实验室 &#xff09;如何有效处理大规模用户数据进行广告推荐&#xff1f;对于互联网企业的发展和进步至关重要。这也是为何快手成立西雅图实验室并实现新一代GPU广告模型训练平台的原因之一。快手新创建的“Persia”GPU广告…

比特币SPV节点启动流程图

2019独角兽企业重金招聘Python工程师标准>>> 比特币SPV节点启动流程图 图小点击右键在新窗口打开 转载于:https://my.oschina.net/penghaozhong/blog/1924687

Android中后台定时任务实现,即时数据同步问题思考!

为什么80%的码农都做不了架构师&#xff1f;>>> 如果你正在找Android后台定时任务实现,那么你找对了,但是其实如果你正在找Java后台任务实现,你就不会找到我的这个博客了.但是我的实现方式没有使用多少Android相关的东西.确实.但是如果你进来了,Thank you!你还是会…

面对996,程序员如何利用“碎片时间”涨薪?

图片来源|视觉中国作为一个程序员&#xff0c;需要不断学习更新知识技能来提升自己。但爆炸式的信息量&#xff0c;总使人抓不到学习重点。所以&#xff0c;笔者为大家筛选了几个程序员会阅读的小众公众号&#xff0c;覆盖全面&#xff0c;囊括了不同的技术类别。小道消息&…

JakartaEE Exception: Invalid bound statement (not found): com.mazaiting.blog.dao.UserDao.selectUs...

异常 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.mazaiting.blog.dao.UserDao.selectUserByNameat org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:227) ~[mybatis-3.4.6.jar:3.4.6]at org.a…

【Qt】AVFrame转QImage

FFmpeg的AVFrame转成Qt的QImage //头文件 #ifdef __cplusplus extern "C" {#endif #include <libavcodec/avcodec.h> #include <libavcodec/avformat.h>

C# 回发或回调参数无效

回发或回调参数无效。在配置中使用 <pages enableEventValidation"true"/> 或在页面中使用<% Page EnableEventValidation"true" %> 启用了事件验证。出于安全目的&#xff0c;此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务…

【QT】Qt正则表达式的使用:使用QRegExp来限制QLineEdit的输入格式

QLineEdit中使用QRegExp来限制输入格式,下面以IP输入框为例 QLineEdit *lineEditIP = new QLineEdit("192.168.147.200", this);QRegExpValidator *reg = new QRegExpValidator(GW::RegExp::ipRegExp(), this)

小小的Python编程故事

现在Python的火热已经不是整个编程界的事情了&#xff0c;Python的火热已经蔓延到小学、大学课程&#xff0c;之前看新闻报道说青岛的小学生课程里都开始设置Python的课程了&#xff0c;大学里由原来必考的VB也改成了Python。一时大家都掀起了学习了Python的热潮&#xff0c;而…

python 验证码识别示例(二) 复杂验证码识别

在这篇博文中手把手教你如何去分割验证&#xff0c;然后进行识别。 一&#xff1a;下载验证码 验证码分析&#xff0c;图片上有折线&#xff0c;验证码有数字&#xff0c;有英文字母大小写&#xff0c;分类的时候需要更多的样本&#xff0c;验证码的字母是彩色的&#xff0c;图…

★核心关注点_《信息系统项目管理师考试考点分析与真题详解》

★核心关注点_《信息系统项目管理师考试考点分析与真题详解》真诚感谢你选用《信息系统项目管理师考试考点分析与真题详解》作为高级项管的辅导用书。对于使用该书的读者们&#xff0c;在备考2012.5.26信息系统项目管理师考试之下午案例分析和论文写作考试时&#xff0c;以下一…