> 웹 프론트엔드 > JS 튜토리얼 > jQuery-1.9.1 소스코드 분석 시리즈 (10) 이벤트 시스템의 이벤트 패키징_jquery

jQuery-1.9.1 소스코드 분석 시리즈 (10) 이벤트 시스템의 이벤트 패키징_jquery

WBOY
풀어 주다: 2016-05-16 15:30:50
원래의
1214명이 탐색했습니다.

이전 글에서는 jQuery-1.9.1 소스코드 분석 시리즈(10) 이벤트 시스템 이벤트 아키텍처를 소개했습니다. 이번 글에서는 계속해서 jquery1에 대한 관련 지식을 소개하겠습니다. 9.1 소스코드 분석 시리즈에 대한 자세한 내용은 아래를 참고하세요.

우선 브라우저의 기본 이벤트가 읽기 전용이므로 이에 대한 jQuery의 작업이 제한된다는 점을 이해해야 합니다. 간단한 예는 jQuery가 새로운 이벤트 객체를 생성해야 하는 이유를 이해하는 데 도움이 될 것입니다.

위임 처리에서는 노드 a가 클릭되면 노드 b에게 fn 함수를 실행하도록 위임합니다. 이벤트가 노드 b에 버블링되면 fn을 실행할 때 컨텍스트 환경이 정확해야 합니다. fn을 실행하는 것은 노드 b가 아니라 노드 a입니다. fn 실행 컨텍스트가 노드 a인지 확인하는 방법: 소스 코드 보기(빨간색 부분)

//执行
ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args );

로그인 후 복사

실행 함수의 컨텍스트를 노드(matched.elem)로 바꾸려면 적용을 사용하세요. 또 다른 요점은 args[0]이 이벤트 객체라는 것입니다. 이벤트가 노드 a의 이벤트인지 확인하는 방법은 무엇입니까? 중요한 속성인 event.currentTarget의 기능이므로 Apply를 실행하기 전 한 단계만 거치면 됩니다

event.currentTarget = matched.elem;
로그인 후 복사

브라우저 로컬 이벤트에서는 불가능한 이벤트 객체의 currentTarget 속성을 직접 변경합니다. 이것이 바로 우리가 로컬 이벤트를 기반으로 jQuery의 이벤트 객체를 구성한 이유입니다.

이벤트에는 마우스 이벤트와 키보드 이벤트 두 가지가 있습니다(터치 이벤트는 언제 추가될지 모르겠습니다). 이 두 가지의 자세한 속성을 살펴보세요

 

그 중 일부는 W3C 표준이 아닌 브라우저 전용입니다. jQuery는 이벤트 속성을 세 부분으로 나눕니다.

마우스 및 키보드 이벤트에 의해 공유되는 속성 jQuery.event.props: "altKey 버블 취소 가능 ctrlKey currentTarget eventPhase MetaKey 관련Target ShiftKey 대상 timeStamp 보기 which".split(" ")

키보드 이벤트별 속성 jQuery.event.keyHooks.props: "char charCode key keyCode".split(" ")

마우스 이벤트별 속성 jQuery.event.mouseHooks.props: "버튼 버튼 clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" ")

a. 새 이벤트 객체 jQuery.event.fix(originalEvent)를 생성합니다

새로운 이벤트 객체 생성은 3단계로 완료됩니다

첫 번째 단계에서는 event = new jQuery.Event(originalEvent)를 사용하여 새 이벤트 객체를 생성하고(new의 역할을 이해하지 못하는 경우 여기를 클릭하세요) isDefaultPrevented, OriginalEvent, type 및 이벤트 생성 시 timeStamp 및 이벤트 표시가 수정되었습니다(불필요한 처리를 피하기 위해 최적화된 사용). jQuery.Event(src, props)의 소스코드는 다음과 같습니다

jQuery.Event = function( src, props ) {
  // Allow instantiation without the 'new' keyword
  if ( !(this instanceof jQuery.Event) ) {
    return new jQuery.Event( src, props );
  }
  //src为事件对象
  if ( src && src.type ) {
    this.originalEvent = src;
    this.type = src.type;
    //事件冒泡的文档可能被标记为阻止默认事件发生;这个函数可以反应是否阻止的标志的正确值
    this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
      src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
  //src为事件类型
  } else {
    this.type = src;
  }
  //将明确提供的特征添加到事件对象上
  if ( props ) {
    jQuery.extend( this, props );
  }
  //创建一个时间戳如果传入的事件不只一个
  this.timeStamp = src && src.timeStamp || jQuery.now();
  //标记事件已经修正过
  this[ jQuery.expando ] = true;
};
로그인 후 복사

첫 번째 단계에서 생성된 이벤트 객체

 

두 번째 단계는 현재 이벤트가 어떤 종류의 이벤트인지 식별한 다음 브라우저의 로컬 이벤트 원본 이벤트에서 해당 속성을 하나씩 복사하는 것입니다

 //创建可写的事件对象副本,并格式化一些特征名称
  var i, prop, copy,
    type = event.type,
    originalEvent = event,
    fixHook = this.fixHooks[ type ];
  if ( !fixHook ) {
    this.fixHooks[ type ] = fixHook =
    //rmouseEvent=/^(?:mouse|contextmenu)|click/
    rmouseEvent.test( type ) ? this.mouseHooks :
    //rkeyEvent=/^key/
    rkeyEvent.test( type ) ? this.keyHooks :
    {};
  }
  //获得要从原生事件中拷贝过来的属性列表
  copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  ...
  //将原生的属性都拷贝到新的事件上
  i = copy.length;
  while ( i-- ) {
    prop = copy[ i ];
    event[ prop ] = originalEvent[ prop ];
  }
로그인 후 복사

세 번째 단계는 관련 속성의 호환성 처리

 // IE<9修正target特征值
  if ( !event.target ) {
    event.target = originalEvent.srcElement || document;
  }
  // Chrome 23+, Safari&#63;,Target特征值不能是文本节点
  if ( event.target.nodeType === 3 ) {
    event.target = event.target.parentNode;
  }
  // IE<9,对于鼠标/键盘事件, 如果metaKey没有定义则设置metaKey==false
  event.metaKey = !!event.metaKey;
  //调用hooks的filter
  return fixHook.filter &#63; fixHook.filter( event, originalEvent ) : event;
로그인 후 복사

코드의 마지막 줄은 마우스 이벤트와 키보드 이벤트에 대해 호환 가능한 적응 처리를 수행합니다.

fixHook.filter는 jQuery.event.keyHooks.filter일 수 있습니다

keyHooks.filter: function( event, original ) {
  //给键盘事件添加which特征值
  if ( event.which == null ) {
    event.which = original.charCode != null &#63; original.charCode : original.keyCode;
  }
  return event;
}
로그인 후 복사

또는 이 jQuery.event.mouseHooks.filter

mouseHooks.filter: function( event, original ) {
  var body, eventDoc, doc,
  button = original.button,
  fromElement = original.fromElement;
  //如果事件pageX/Y特征不见了,用可用的clientX/Y来计算出来
  if ( event.pageX == null && original.clientX != null ) {
    eventDoc = event.target.ownerDocument || document;
    doc = eventDoc.documentElement;
    body = eventDoc.body;
    event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
    event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
  }
  //如果必要的话添加relatedTarget特征
  if ( !event.relatedTarget && fromElement ) {
    event.relatedTarget = fromElement === event.target &#63; original.toElement : fromElement;
  }
  //添加点击事件which特征值: 1 === left; 2 === middle; 3 === right
  //备注:button不标准,因此不要是使用
  if ( !event.which && button !== undefined ) {
    event.which = ( button & 1 &#63; 1 : ( button & 2 &#63; 3 : ( button & 4 &#63; 2 : 0 ) ) );
  }
  return event;
}
로그인 후 복사

최근 완료된 이벤트 객체는 다음과 같습니다. (마우스 이벤트를 예로 들겠습니다)

 

원본 이벤트는 originalEvent에 저장되고, target은 대상 노드(위임 노드, 이벤트 소스)를 저장하고, 기타 정보는 생략합니다

b.오버로드 이벤트 방식

새 이벤트 객체 event = new jQuery.Event(originalEvent)를 생성하면 해당 이벤트는 jQuery.event.prototype의 메서드를 상속합니다. 방법을 살펴보겠습니다

 

이전에 jQuery.event.prototype에서 오버로드된 stopPropagation 메서드의 역할을 분석했습니다. 버블링을 방지하기 위해 이벤트 개체의 메서드를 호출하는 것 외에도 위임된 노드에 처리 대기 중인 위임 이벤트가 여러 개 있을 때의 역할도 있습니다. , event.stopPropagation()을 호출하는 이벤트 중 하나는 후속 이벤트 처리 실행을 방지합니다. 볼 키워드를 검색하려면 여기를 클릭하세요

PreventDefault 함수도 비슷한 효과를 가집니다. 이 코드는 PreventDefault 함수에 추가되었습니다

this.isPropagationStopped = returnTrue;
로그인 후 복사

在触发事件trigger函数和模拟冒泡simulate函数中都会根据isPropagationStopped()判断是否要执行DOM节点的默认操作。源码如下

isImmediatePropagationStopped是stopPropagation特殊用法,isImmediatePropagationStopped会直接阻止掉当前的处理和后面等待执行的事件处理,而stopPropagation会执行完当前的处理,然后阻止后面等待执行的事件处理。

源码如下

// jQuery.Event基于DOM事件所指定的ECMAScript语言绑定
// http://www.w.org/TR//WD-DOM-Level--Events-/ecma-script-binding.html
jQuery.Event.prototype = {
  isDefaultPrevented: returnFalse,
  isPropagationStopped: returnFalse,
  isImmediatePropagationStopped: returnFalse,
  preventDefault: function() {
    var e = this.originalEvent;
    this.isDefaultPrevented = returnTrue;
    if ( !e ) {return; }
    if ( e.preventDefault ) {
      e.preventDefault();
    //IE支持
    } else {
      e.returnValue = false;
    }
  },
  stopPropagation: function() {
    var e = this.originalEvent;
    this.isPropagationStopped = returnTrue;
    if ( !e ) {return; }
    if ( e.stopPropagation ) {
      e.stopPropagation();
    }
    // IE支持
    e.cancelBubble = true;
  },
  stopImmediatePropagation: function() {
    this.isImmediatePropagationStopped = returnTrue;
    this.stopPropagation();
  }
}
로그인 후 복사

以上就是本文给大家介绍的jQuery-1.9.1源码分析系列(十)事件系统之事件包装,希望大家喜欢。

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿