Events have always been one of the most powerful objects in JavaScript. JavaScript provides two methods, addEventListener and attachEvent, to bind events to DOM nodes. jquery further encapsulates them and provides a bind method compatible with various browsers. Now, this traditional event binding method has the following shortcomings:
1. You may need to bind a lot of EventHanders.
If there are 100 rows in a table on the page, a click event must be bound to each row. Then 100 EventHandlers must be bound, which puts a huge burden on page performance because more memory needs to be created to store these Handlers.
2. The event cannot be added after binding to the DOM node.
If the code on the page is as follows:
Copy the code code as follows:
$("#dv").bind('click',function(){alert('test');});
$(body).append('<div id="dv">test</div>')
The div added later cannot trigger click events.
In order to solve these two problems, JavaScript introduced event proxy (event proxy). First, let’s understand the bubbling mechanism in js.
Basically all browsers support event bubbling. When an event is triggered on a DOM node, the event will be propagated all the way up to the root node of the document. Since all node events will eventually be delivered to the document root node, if we directly bind the event to the document root node (document node), and then use event.target to determine which node triggered the event, will it reduce a lot of EventHandlers? What about the binding?
The live method in jquery is officially implemented based on this principle. Let’s implement a simple version of live:
Copy the code code as follows:
$.fn.mylive=function(eventType,fn){
var that=this.selector;
$(document).bind(eventType,function(event){
var match=$(event.target).closest(that)
if(match.length !== 0){
fn.apply($(event.target),[event]);
}
})
}
$("#tb td").mylive('click',function(event){
alert(event.target.innerHTML);
});
var tb='<table id="tb"> /
<tr> /
<td>the first column</td>/
<td>the second column</td>/
<td>the third column</td>/
</tr>/
</table>';
$("body").append(tb);
In the live method, the event is bound to the document node, and $(event.target).closest(that) matches the element that actually triggered the event. In the demo, we bound the click event for each TD added later. When we click on different TDs, we find that their corresponding Text prompt boxes will pop up.
The live method makes up for the two shortcomings of the traditional event binding method mentioned earlier. But the live method still has its shortcomings. Look at this code:
Copy the code code as follows:
$("#tb td").mylive('click',function(event){
alert(event.target.innerHTML);
});
It will first traverse the entire document based on the jquery selector, find all #tb td elements, and store them as objects. However, in the live implementation method, these objects are not used, but only "#td td" is used as a string to match the event source. This greatly increases a lot of unnecessary consumption.
So is there any way to improve this situation? The delegate proxy method is provided in jQuery, which supports binding events to specified elements, not just documents. Understand its principle, let's implement a simple version of delegate:
Copy the code code as follows:
$(body).append('<div id="dv"></div>');
$.fn.mydelegate=function(selector,eventType,fn){
$(this).bind(eventType,function(event){
var match=$(event.target).closest(selector);
if(match.length !== 0){
fn.apply($(event.target),[event]);
}
});
}
$("#dv").mydelegate('td','click',function(event){
alert(event.target.innerHTML);
});
var tb='<table id="tb"> /
<tr> /
<td>the first column</td>/
<td>the second column</td>/
<td>the third column</td>/
</tr>/
</table>';
$("dv").append(tb);
The mydeletage method does not need to obtain all td objects, but only the div objects to which the event is bound. This is better than the live method in terms of execution efficiency.
This is just an introduction to let everyone understand the principle of event proxy. The implementation of live and delegate in jquery is much more complicated.