이벤트는 항상 JavaScript에서 가장 강력한 개체 중 하나였습니다. JavaScript는 이벤트를 DOM 노드에 바인딩하기 위해 addEventListener 및 attachmentEvent라는 두 가지 메서드를 제공합니다. jquery는 이를 추가로 캡슐화하고 다양한 브라우저와 호환되는 바인딩 메서드를 제공합니다. 이제 이 전통적인 이벤트 바인딩 방법에는 다음과 같은 단점이 있습니다.
1. 많은 EventHanders를 바인딩해야 할 수도 있습니다.
페이지의 테이블에 100개의 행이 있는 경우 클릭 이벤트가 각 행에 바인딩되어야 합니다. 그런 다음 100개의 EventHandler를 바인딩해야 하며, 이는 이러한 핸들러를 저장하기 위해 더 많은 메모리를 생성해야 하기 때문에 페이지 성능에 큰 부담을 줍니다.
2. DOM 노드에 바인딩한 후에는 이벤트를 추가할 수 없습니다.
페이지의 코드가 다음과 같은 경우:
다음과 같이 코드 코드를 복사합니다.
$("#dv").bind('click',function(){alert('test');});
$(body).append('<div id="dv">테스트</div>')
나중에 추가된 div는 클릭 이벤트를 실행할 수 없습니다.
이 두 가지 문제를 해결하기 위해 JavaScript에서는 이벤트 프록시(Event Proxy)를 도입했습니다. 먼저 js의 버블링 메커니즘을 이해해 보겠습니다.
기본적으로 모든 브라우저는 이벤트 버블링을 지원합니다. DOM 노드에서 이벤트가 트리거되면 해당 이벤트는 문서의 루트 노드까지 전파됩니다. 모든 노드 이벤트는 결국 문서 루트 노드로 전달되므로 이벤트를 문서 루트 노드(문서 노드)에 직접 바인딩한 다음 event.target을 사용하여 이벤트를 트리거한 노드를 확인하면 많은 작업이 줄어들까요? EventHandler는 어떻습니까?
jquery의 live 메소드는 이 원칙에 따라 공식적으로 구현됩니다. live의 간단한 버전을 구현해 보겠습니다.
다음과 같이 코드 코드를 복사합니다.
$.fn.mylive=함수(이벤트 유형,fn){
var that=this.selector;
$(문서).bind(이벤트 유형,함수(이벤트){
var match=$(event.target).closest(그)
if(match.length !== 0){
fn.apply($(event.target),[이벤트]);
}
})
}
$("#tb td").mylive('클릭',function(event){
경고(event.target.innerHTML);
});
var tb='<테이블 id="tb"> /
<tr> /
<td>첫 번째 열</td>/
<td>두 번째 열</td>/
<td>세 번째 열</td>/
</tr>/
</table>';
$("본문").append(tb);
라이브 메서드에서 이벤트는 문서 노드에 바인딩되며 $(event.target).closest(that)는 실제로 이벤트를 트리거한 요소와 일치합니다. 데모에서는 나중에 추가된 각 TD에 대한 클릭 이벤트를 바인딩했습니다. 다른 TD를 클릭하면 해당 텍스트 프롬프트 상자가 팝업됩니다.
라이브 방식은 앞서 언급한 전통적인 이벤트 바인딩 방식의 두 가지 단점을 보완합니다. 그러나 라이브 방식에는 여전히 단점이 있습니다. 이 코드를 보세요:
다음과 같이 코드 코드를 복사합니다.
$("#tb td").mylive('클릭',function(event){
경고(event.target.innerHTML);
});
먼저 jquery 선택기를 기반으로 전체 문서를 탐색하고 모든 #tb td 요소를 찾아 개체로 저장합니다. 그러나 라이브 구현 방식에서는 이러한 객체를 사용하지 않고 "#td td"만 문자열로 사용하여 이벤트 소스와 일치시킵니다. 이로 인해 불필요한 소비가 많이 증가합니다.
그렇다면 이러한 상황을 개선할 수 있는 방법은 없을까요? 위임 프록시 메서드는 문서뿐만 아니라 지정된 요소에 대한 바인딩 이벤트를 지원하는 jQuery에서 제공됩니다. 그 원리를 이해하고 간단한 버전의 대리자를 구현해 보겠습니다.
다음과 같이 코드 코드를 복사합니다.
$(body).append('<div id="dv"></div>');
$.fn.mydelegate=기능(선택기,이벤트 유형,fn){
$(this).bind(eventType,function(event){
var match=$(event.target).closest(selector);
if(match.length !== 0){
fn.apply($(event.target),[이벤트]);
}
});
}
$("#dv").mydelegate('td','click',function(event){
경고(event.target.innerHTML);
});
var tb='<테이블 id="tb"> /
<tr> /
<td>첫 번째 열</td>/
<td>두 번째 열</td>/
<td>세 번째 열</td>/
</tr>/
</table>';
$("dv").append(tb);
mydeletage 메소드는 모든 td 객체를 획득할 필요가 없고 이벤트가 바인딩된 div 객체만 획득할 필요가 있습니다. 이는 실행 효율성 측면에서 라이브 방식보다 우수합니다.
이는 모든 사람이 이벤트 프록시의 원리를 이해할 수 있도록 하기 위한 소개일 뿐입니다. jquery에서 라이브 및 대리자 구현은 훨씬 더 복잡합니다.