-
jquery event trigger 分析
- 注册了事件,如onclick。那么当用户点击这个元素时,就会自动触发这个事件的已经注册的事件处理函数。但是我们有的时候要采用程序来模拟事件的触发就得采用强迫触发某个事件。在IE中我们可以采用.fireEvent()来实现。如:<form onsubmit="a()" >中,如果button的form.submit()的方式提交表单,是不会主动触发onsumbit事件的,如果必须的话,就要在submit前$(“:form”)[0].fireEvent("onsubmit”,),这样就会触发该事件。
- 在mozilla中有三个步骤: var evt = document.createEvent('HTMLEvents');
- evt.initEvent('change',true,true); t.dispatchEvent( evt );
- 在prototype是采用这样的方式来实现的。那么jquery中呢,它的实现方式有一点不一样。
- trigger : function(type, data, fn) {
- return this.each(function() {
- jQuery.event.trigger(type, data, this, true, fn);
- }); },
- Trigger有三个参数,data参数是为了注册的事件函数提供了实传。如果data[0]中preventDefault存在,data[0]就可以做为用户自定义的包裹事件的空间。Fn是可以为事件提供一个即时即用的事件处理方法。也就是在没有注册事件的情况下也可以通过传入处理函数来处理事件。如果已经注册了,那就是在原来的事件处理函数之后执行。
-
- triggerHandler : function(type, data, fn) {
- return this[0]&& jQuery.event.trigger(type,data,this[0],false,fn);
- },
- triggerHandle通过把jQuery.event.trigger的donative参数设为false,来阻止执行浏览器默处理方法。它与trigger不现的一点,还在于它只是处理jquery对象的第一个元素。
- 上面两个方法都调用了jQuery.event.trigger来完成任务:
- trigger : function(type, data, elem, donative, extra) {
- data = jQuery.makeArray(data);
-
-
- if (type.indexOf("!") >= 0) { ①
- type = type.slice(0, -1);var exclusive = true;
- }
- if (!elem) {
- if (this.global[type])
- jQuery.each(jQuery.cache, function() {
-
- if (this.events && this.events[type])
- jQuery.event.trigger(type, data, this.handle.elem);
- });
- } else {
- if (elem.nodeType == 3 || elem.nodeType == 8) return undefined;
- var val, ret, fn = jQuery.isFunction(elem[type] || null),
-
-
-
- event = !data[0] || !data[0].preventDefault;
-
- if (event) {
- data.unshift( { type : type,target : elem,
- preventDefault : function() {},stopPropagation :
- function() {}, timeStamp : now() });
- data[0][expando] = true;
- }
- data[0].type = type;
-
- if (exclusive) data[0].exclusive = true;
-
-
-
-
-
-
-
-
-
-
- var handle = jQuery.data(elem, "handle"); ⑤
- if (handle)val = handle.apply(elem, data);
-
-
-
- if ((!fn || (jQuery.nodeName(elem, 'a') && type == "click")) ⑥
- && elem["on"+ type]&& elem["on"+type].apply(elem,data) === false)
- val = false;
-
-
-
- if (event) data.shift();
-
- if (extra && jQuery.isFunction(extra)) { ⑦
- ret = extra.apply(elem, val == null ? data : data.concat(val));
-
-
- if (ret !== undefined) val = ret;
- }
-
-
-
-
- if (fn && donative !== false && val !== false ⑧
- && !(jQuery.nodeName(elem, 'a') && type == "click")) {
- this.triggered = true;
- try {elem[type]();
- } catch (e) {}
- }
- this.triggered = false;
- }
- return val;
- },
- Jquery的fire事件的方法与prototype中实现是完全不一样的。Ext、YUI没有提供强迫触发事件的方法。对于一般的思维,程序来触发浏览器的事件就应该采用fireEvent或dispatchEvent方法来运行。
- 但是jquery采用一种不同的方法。对于通过jquery.event.add来注册的事件(不管是自定义的还是注册到浏览器事件),它保存在一个与元素及事件名相对应的cache中。在浏览器的触发中,这个是没有什么作用。但是它是为了通过等程序来强迫触发时,从cache中取到对应的事件处理函数。这个时候就抛开了浏览器的事件。在这里还可以执行一些自定义的事件函数。如⑤处。
- 对于通过html的标签中如click或elem.onclick=function(){}形式注册的事件函数。在⑥处它采用执行元素的如onclick形式的回调函数就可以。通过这种dom0的方式只能注册一个函数。
- 有的时候,如果没有onclick这样的事件处理函数,浏览器会执行默认的处理函数。如form.submit()。⑧处可以看出对于这样的默认的事件处理,还可以通过参数donative来控制。
- 程序手动强迫触发事件,有一点问题就是event是怎么生成,就是没有浏览器生成event传入到函数中。Prototype采用了是新生成的dataavailable的事件。这样的事件也没有什么作用。Jquery也采用fake的方式伪造一个一个事件,如④,它比prototype的事件好处在于它能通过trigger的函数的参数来传入需要的event。Prototype则不能。
- 通过上面的分析,隐隐可以看出Jquery是通过模拟浏览器的触发事件的执行过程来构建这个trigger的函数的。先执行dom1方式(addEvent)注册的事件,再执行dom0方式注册的事件,最后看看要不要执行默认的事件处理。
- 在⑦处,我们可以看出trigger还可能通过传入回调函数和参数来完成对执行的事件处理函数的结果进行判断处理,形成新结果通过trigger的函数返回。这在有的时候是很有用的。
- 除了这些,它还能对于事件的处理函数进行分类(namespace),可以在合适的时候调用事件的不同分类的的处理函数(通过jquery.event.add来注册)。这个分类的处理在handle实现。
- handle : function(event) {
-
- var val, ret, namespace, all, handlers;
-
- event = arguments[0] = jQuery.event.fix(event || window.event);
-
- namespace = event.type.split(".");
- event.type = namespace[0];
- namespace = namespace[1];
-
-
- all = !namespace && !event.exclusive;
-
- handlers = (jQuery.data(this, "events") || {})[event.type];
- for (var j in handlers) {
- var handler = handlers[j];
-
- if (all || handler.type == namespace) {
-
- event.handler = handler;
- event.data = handler.data;
- ret = handler.apply(this, arguments);
- if (val !== false)
- val = ret;
- if (ret === false) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- return val; },
- handle的主要功能是就是分类且有序地执行事件的所有的注册的处理函数。
-
相关阅读:
逍遥刘强 - 期货大作手风云录(2015年8月28日)
雷米 - 心理罪:画像(2015年8月17日)
雷米 - 心理罪:城市之光(2015年8月11日)
雷米 - 心理罪:暗河(2015年8月9日)
雷米 - 心理罪:教化场(2015年8月8日)
付海棠 - 一个农民的亿万传奇(2015年7月14日)
阿西莫夫 - 神们自己(2015年6月23日)
张维为 - 中国震撼:一个”文明型国家“的崛起(2015年5月30日)
华彬 - 华彬讲透孙子兵法(2015年5月22日)
股峰求道 - 炼股成金:从散户到操盘手的修炼法则(2015年5月11日)
-
原文地址:https://www.cnblogs.com/rooney/p/1346470.html
Copyright © 2020-2023
润新知