博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
jQuery源码分析--Event模块(3)
阅读量:4686 次
发布时间:2019-06-09

本文共 6164 字,大约阅读时间需要 20 分钟。

  最后剩下了事件的手动触发了。jQuery提供了两个函数trigger和triggerHandler来手动触发事件,可以触发原生事件和自定义的事件。这个触发不单只会触发有jQuery绑定事件,而且也会触发原生的行内绑定事件。trigger和triggerHander的区别是:

  trgger:会对匹配的所有元素都调用jQuery.event.trrger,而且会冒泡,会触发浏览器默认行为。返回值为jQuery对象
  triggerHandler:只会对第一个匹配的元素调用jQuery.event.trrger,而且不会冒泡,不会触发浏览器默认行为。为函数的返回值
  可以看到都是通过底层的jQuery.event.trrger工具方法来实现。那jQuery.event.trrger是如何工作的呢。

  1. 构造从当前节点到window的一个冒泡路径,用数组来存储。
  2. 遍历这个路径数组,在没有被阻止冒泡的情况下,调用每个节点的jQuery的主监听函数 和 元素的行内监听函数。
  3. 最后用原生的事件触发函数(click,focus)来触发默认行为。并设定一个jQuery.event.triggered标志来标志是触发默认行为,避免再次触发事件。
    最后是源代码。
    trigger: function( event, data, elem, onlyHandlers ) {
    //event 可以是事件类型、自定义事件对象或jquery事件对象 var i, cur, tmp, bubbleType, ontype, handle, special, eventPath = [ elem || document ],//冒泡路劲 type = hasOwn.call( event, "type" ) ? event.type : event,//判断event是对象(自定义和jquery)还是类型字符串 namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];//命名空间 cur = tmp = elem = elem || document;//cur指向当前元素的祖先元素 // Don't do events on text and comment nodes if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
    //排除文本节点和注释节点 return; } // focus/blur morphs to focusin/out; ensure we're not firing them right now rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
    //过滤掉foces/blur事件的默认行为,后面统一用focusin/focusout return; } if ( type.indexOf(".") >= 0 ) {
    //解析事件类型和命名空间并对命名空间排序 // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } ontype = type.indexOf(":") < 0 && "on" + type;//有:号时不调用行内监听事件 // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[ jQuery.expando ] ?//判断是不是jquery监听对象,不是创建。 event : new jQuery.Event( type, typeof event === "object" && event ); // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3; event.namespace = namespaces.join("."); event.namespace_re = event.namespace ? new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : null; // Clean up the event in case it is being reused event.result = undefined;//最后一个有返回值的函数的返回值 if ( !event.target ) {
    //修正target event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ?//将附加数据(如果有)和事件对象封装成数组。方便apply调用 [ event ] : jQuery.makeArray( data, [ event ] ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
    //先调用修正对象的触发函数来触发 return; } // Determine event propagation path in advance, per W3C events spec (#9951) 构造冒泡路劲 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
    //排除onlyHandlers=true、load、已经到window对象了 bubbleType = special.delegateType || type;//优先使用修正对象的属性 if ( !rfocusMorph.test( bubbleType + type ) ) {
    //初始化cur为当前元素的父元素(排除focus/blur) cur = cur.parentNode; } for ( ; cur; cur = cur.parentNode ) {
    //遍历 eventPath.push( cur ); tmp = cur;//tmp指向所能到达的最顶层元素 } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( tmp === (elem.ownerDocument || document) ) {
    //如果最顶层是document再添加window eventPath.push( tmp.defaultView || tmp.parentWindow || window ); } } // Fire handlers on the event path i = 0; while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
    //遍历冒泡路劲 触发监听函数 event.type = i > 1 ? bubbleType : special.bindType || type; // jQuery handler handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );//取出主监听函数 if ( handle ) {
    //调用主监听函数 handle.apply( cur, data ); } // Native handler handle = ontype && cur[ ontype ]; if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
    //执行行内事件监听函数 event.result = handle.apply( cur, data ); if ( event.result === false ) {
    //返回值为false代表阻止默认行为 event.preventDefault(); } } } event.type = type;//回复type // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) {
    //没有阻止默认行为 if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Don't do default actions on window, that's where global variables be (#6170) if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method 避免再次触发行内监听函数 tmp = elem[ ontype ]; if ( tmp ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above 避免再次触发主函数 jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( tmp ) {
    //恢复 elem[ ontype ] = tmp; } } } } return event.result; },

     

转载于:https://www.cnblogs.com/dq-Leung/p/4341552.html

你可能感兴趣的文章
Sublime Text 3 注册码
查看>>
linux 后台运行命令
查看>>
[内核编程] 寒假学习内核编程小结
查看>>
本地电脑配ssh key的几个命令
查看>>
Overcoming Life's Obstacles - ASC 2017 March 03-04
查看>>
多校第十场
查看>>
MFC VS2008添加消息映射
查看>>
2012结束单身,与TA的婚礼你选哪?
查看>>
个人编程项目作业
查看>>
LINUX下解决TIME_WAIT等网络问题
查看>>
开启主机的TELNET服务centos6x-7X
查看>>
JS函数实现和递归实现斐波那契数列 || js两种方法实现斐波那契数列
查看>>
TJOI2015题解
查看>>
@synthesize of 'weak' property is only allowed in ARC or GC mode
查看>>
Android service介绍和启动方式
查看>>
LaTeX技巧:如何高效地将LaTeX代码转为Word公式
查看>>
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字...
查看>>
如何在VS2010中使用代码片段
查看>>
H3C 通配符掩码的应用示例
查看>>
sqlite 测试索引
查看>>