Getting Started with JavaScript event agents

Source: Internet
Author: User
Tags add implement log return tagname version

Event delegation, also called an event delegate. is a common technique for binding events commonly used in JavaScript.

As the name implies, "event Agent" is to delegate the original need to bind the event to the parent element, so that the parent element to assume the role of event monitoring.



Why do you do it?

As we all know, DOM operations are very performance-intensive. So repetitive event bindings are simply a performance killer. The core idea of the event agent is to monitor as many events as possible by binding as few as we can.



The following will show you how to implement the event agent with Zepto.

Ah? What is Zepto?

Zepto is a minimalist JavaScript library to modern browsers with a largely jquery-compatible API. If You use JQuery, you already know the how to use Zepto.

Because the API is compatible with jquery, child shoes that are familiar with jquery have almost no learning cost to use Zepto. The demo code can actually work on jQuery as well. And the current zepto is more in the mobile end, a far away from the old version of IE in the world.



So why not just use jquery?

Because the following will be a brief analysis of the source code, but jquery inside in order to compatible with the old version of IE made a lot of compromises, the source is very not intuitive. And Zepto is designed for modern browsers, the use of most of the APIs are in line with the standards of the consortium, more intuitive analysis.



Take this HTML structure for example:

<ul class= "List" >
<li class= "List_items" >000</li>
<li class= "List_items" >111 <a href= "javascript:void (0);" >link</a></li>
<li class= "List_items" >222 <i>italic</i></li>
<li>333</li>
</ul>



In general, this binds the event:

$ (". List_items"). On ("click", Function (e) {
Console.log (E.target.tagname);
Console.log (This.tagname);
});

Deom>>

Open the Console of your browser and look, you'll find that every. list_items element is bound to the Click event, and the bound object is li.list_items. The following figure:

This means that the zepto is actually traversing all the. List_items elements and binding the Click event One at a-a-byte.

The implementation idea is the same as the following native JavaScript code:

[].foreach.call (Document.queryselectorall (". List_items"), function (Elem) {
Elem.addeventlistener ("click", Function (e) {
Console.log (E.target.tagname);
Console.log (This.tagname);
}, False);
});

In this way, the performance overhead is very high when you encounter an extremely long list (UL) and table (table).

For example: UL has 1000 Li, need to do 1000 times of event binding.

And the event agent, is applied to this kind of scene.

Let's take a look at the official API documentation for ZEPTO:

The on method also supports passing in a [selector] value before the callback function, and this [selector] is the element that actually needs to listen for the event.

Take a look at the actual example:

$ (". List"). On ("click", ". List_items", function (e) {
Console.log (E.target.tagname);
Console.log (This.tagname);
});

Demo>>

The Click event Agent is used on the ul.list element by the on method to listen for clicks on all of its. List_items's child elements.

Open the browser Console to see:

Although each. List_items is prompted for event listening, their bound objects are pointing to ul.list.

What mechanism does the event agent implement?

The core idea of this is event bubbling (Bubble) . But here I'm not going to elaborate on the event bubbling because it's going to be a big topic. Google, you can find a lot of relevant introduction.

Below we look at the source code of Zepto, it is how to deal with this event agent.

Implementation of method on:
$.fn.on = function (event, selector, data, callback, one) {
var autoremove, delegator, $this = this
if (Event &&!isstring (event)) {
$.each (event, function (type, fn) {
$this. On (type, selector, data, FN, one)
})
Return $this
}

if (!isstring (selector) &&!isfunction (callback) && callback!== false)
callback = data, data = selector, selector = undefined
if (isfunction (data) data = = False)
callback = data, data = undefined

if (callback = false) callback = Returnfalse

Return $this. Each (function (_, Element) {
if (one) Autoremove = function (e) {
Remove (element, E.type, callback)
Return callback.apply (this, arguments)
}

if (selector) delegator = function (e) {
var evt, match = $ (e.target). Closest (selector, Element). Get (0)
if (match && match!== Element) {
EVT = $.extend (Createproxy (E), {currenttarget:match, livefired:element})
Return (Autoremove callback). Apply (match, [Evt].concat (Slice.call (arguments, 1))
}
}

Add (element, event, callback, data, selector, delegator autoremove)
})
}

The approximate execution flow of the code is as follows:

As you can see from the activity diagram above, most of the logic is used to handle the incoming arguments on the on method, and the Delegator function is the key to the event agent.

As for the Add method, it mainly deals with certain special events, such as ready, hover, etc. As a black box to see, it is equivalent to the original AddEventListener method.

Here's a breakdown of the implementation logic of the Delegator function:

It should be clear to all of us here.

When the on method is invoked for event binding, the event agent is implemented only if the [selector] parameter is passed in.

How do you write event bindings with JavaScript native code in practical applications? As follows:
var Listelem = Document.queryselector (". List");
Listelem.addeventlistener ("click", Function (e) {
var delegatetarget = this,
Firetarget = E.target,
Eventtarget;

if (firetarget.classname!== "List_items") {
function Findparent (elem) {
if (Elem = = Delegatetarget) {
return null;
}
var parent = Elem.parentnode;
if (Parent.classname = = "List") {
return null;
}
if (Parent.classname = = "List_items") {
return to parent;
}
Findparent (parent);
}
Eventtarget = Findparent (firetarget);
} else {
Eventtarget = Firetarget;
}
if (!eventtarget) return false;
Console.log ("Firetarget:" + firetarget.tagname);
Console.log ("Eventtarget:" + eventtarget.tagname);
}, False);

Demo>>



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.