Parsing of events in JavaScript (verbose)

Source: Internet
Author: User
This article brings you the content of JavaScript in the analysis of the event (detailed), there is a certain reference value, the need for friends can refer to, I hope to help you.

The relationship between JavaScript, browser, events

The JavaScript program uses the asynchronous event-driven programming (Event-driven programming) model, which is explained by Wikipedia:

Event-driven programming (Event-driven programming) is a computer program design model. This model of the program running process is by the user's actions (such as the mouse button, keyboard key action) or by the message of other programs to determine. The process of running a program is determined by the programmer relative to the batch programming. Batch programming is a way of teaching in the primary programming curriculum. However, the design model of event-driven programming is conceived in the context of interactive programs (Interactive program)

In short, in Web front-end programming, JavaScript receives user input by using the event model API and user interaction provided by the browser.

Because the user's behavior is indeterminate. This scenario is not possible with the traditional synchronous programming model, because you cannot execute the following code until the user has finished working. So asynchronous events are used in JavaScript, which means that theevents in JS are executed asynchronously .

The basic implementation principle of the event driver model is essentially the use of event loops, which involves the browser event model and the callback principle.

JavaScript DOM, BOM model, also asynchronous and settimeout,xmlhttprequest such API is not the JavaScript language itself.

Method of Event binding

There are 3 methods of event binding:

Inline binding

The binding event handler is set directly on the DOM element on + eventType . For example:

<a href= "#none" onclick= "alert (' clicked ')" > click me </a>

There are two drawbacks to this approach:

    1. The event handlers and HTML structures are mixed together and do not conform to the MVX specification. In order to separate content, performance and behavior, we should avoid this writing.

    2. The code that is written in this way determines that there is a global scope that may produce a naming conflict, leading to unforeseen serious consequences.

Overriding the event callback function directly on the DOM element

Using the on + EventType property API above the DOM element

var el = getElementById (' button ');  The button is a <button> element el.onclick = function () {alert (' button clicked. ')}; El.onclick = function () {Alert (' button Clicked. ')};//actual popup ' button Clicked. ', function has been overwritten

This approach also has a drawback: the post-bound function overwrites the previous function. For example, we register a window.onload event that may overwrite an existing event function in a library. Of course, this can be solved by:

function addevent (element, EventName, fun) {   //eventname = ' on ' + EventType    var oldfun = element[eventname];    if (typeof oldfun!== ' function ') {        element[eventname] = fun;    } else {        Element[eventname] = function () {            O Ldfun ();            Fun ();}        ;}    } addevent (window, "onload", function () {alert (' onload 1 ')}), Addevent (window, "onload", function () {alert (' onload 2 ')});

Of course, the DOM ready is generally used, because JavaScript can be executed after the DOM has loaded.

Standard Binding method

There are two standard binding methods, AddEventListener and attachevent, which are supported by standard browsers, which are APIs supported by IE8 browsers:

For example, give a button register Click event var el = getElementById (' button ');  The button is a <button> element if (el.addeventlister) {    el.addeventlistener ("click", Function (e) {        alert (" Button clicked. ");    },false);} if (el.attachevent) {    el.attachevent ("onclick", function (e) {        alert ("button clicked.");}    );

It is important to note that:

    1. The first parameter of the Addeventlister event type is not prefixed with an on, while the attachevent needs an on prefix.

    2. The This in the event callback function in Addeventlister points to the event element target itself, while this of the event callback function in attachevent points to window.

    3. Addeventlister has a third argument, true indicates that the event is working in the capture phase, and false is the bubbling phase (default: false). And attachevent can only work in the bubbling phase.

Run the following code in Chrome:

<a href= "Javascript:alert (1)" onclick= "alert (2)" id= "link" >click me</a><script>    var link = document.getElementById (' link ');    Link.onclick = function () {alert (3);};  Overrides the onclick definition in the line    link.addeventlistener (' click ', function () {alert (4);},false);    Link.addeventlistener (' click ', function () {alert (5);},false);</script>

Click after the pop-up sequence is: 3, 4, 5, 1

Here the 4th line of code overrides the onclick definition within the row, and if this line is commented, the input order is: 2, 4, 5 and 1, and no overwrite occurs between AddEventListener.

Unbind events

For the first two methods above, unbinding an event requires only the corresponding event function to be set to null:

var el = document.getElementById (' button '); el.onclick = null;

For the third method above, use the Removelisten () method, in IE8, corresponding to use DetachEvent (). Note that they correspond to the above registration method one by one and cannot be mixed.

This is an error code, cannot implement event removal//Build an event var el = document.getElementById (' button ');  The button is a <button> element if (el.addeventlister) {    el.addeventlistener ("click", Function (e) {        alert (" Button clicked. ");    },false);} if (el.attachevent) {    el.attachevent ("onclick", function (e) {        alert ("button clicked.");}    ); An attempt was made to remove this event if (el.removeeventlister) {    el.addeventlistener ("click", Function (e) {        alert ("button clicked.");    } , false);} if (el.detachevent) {    el.datachevent ("onclick", function (e) {        alert ("button clicked.");}    ); Removal failed

The above error is when the event function is defined, although it looks exactly the same, but in memory the address is not the same. In this way, the computer does not think that the release and binding is the same function, nature will not be lifted correctly. It should be written like this:

Create an event var el = document.getElementById (' button ');  The button is a <button> element var handler = function (e) {alert ("button clicked.");}; if (el.addeventlister) {    el.addeventlistener ("click", Handler,false);} if (el.attachevent) {    el.attachevent ("onclick", handler);} An attempt was made to remove this event if (el.removeeventlister) {    el.addeventlistener ("Click", Handler, false);} if (el.detachevent) {    el.datachevent ("onclick", handler);} Removal success

Capturing and bubbling of events

Before saying that the third parameter of the AddEventListener function represents capture and bubbling, this is a focus!

I'll describe for myself what their definition is:

bubbling: An event triggered on an element that, in turn, triggers the event from inside to outside on the parent element of the element until the window element.

capture : An event triggered on an element that triggers the event on all child elements of each layer of the element, and is layered inward until all elements no longer have child elements.

such as (note: Pictures from Baidu search)

The return to function parameter between events is an event object that includes many event properties and methods, for example, we can block bubbling and default events in the following ways:

This example only writes the handler function handler (event) {    event = Event | | window.event;    Block bubbling    if (event.stoppropagation) {        event.stoppropagation ();      Standard Method    } else {        event.cancelbubble = true;    IE8    }    //organization default event    if (event.perventdefault) {        event.perventdefault ();      Standard Method    } else {        event.returnvalue = false;    IE8    }}

Second, normal registration events can only block default events and cannot prevent bubbling

element = Document.getelemenbyid ("Submit"), Element.onclick = function (e) {    /*...*/    return false;    Block bubbling by returning false}

Event Object

One parameter in the event function is the event object, which contains all the information about the occurrence of the event, such as when the keyboard time includes what buttons were clicked, what key combinations are included, and the mouse events include a series of screens with various coordinates and click types, even drag and drop. Of course, it also contains a lot of DOM information, such as clicked on what element, dragged into what element, the current state of the event and so on.

Here are some important things to emphasize about event compatibility:

Document.addeventlistener (' click ', Function (event) {Event    = Event | | | window.event;   The object is a    console.log (event) registered on the window;   Can output event object look, properties many many    var target = Event.target | | event.srcelement;  The former is the standard event target, the latter is IE's event target},false);

For a question about mouse event coordinates, you can read another blog: Distance properties for element and mouse events

Event triggering

In addition to user actions, we can also write code to actively trigger an event, taking the Ele element's Click event as an example:

Ele.click ();   Trigger a Click event on a ele element

Event Proxy

Sometimes we need to bind events to a DOM element that does not exist, such as an element that the user dynamically adds, or a DOM node that is rendered after an Ajax request is completed. The logic of the generic binding event executes before rendering, but the element cannot be found when it is bound and cannot be successful.

In order to solve this problem, we usually use the event Proxy/delegate (delegation). And, in general, the performance of using event proxies is much higher than a single-bound event, let's look at an example.

    • Traditional registration event methods, which are inefficient when content is large and do not support the dynamic addition of elements

<ul id= "List" >    <li>item-1</li>    <li>item-2</li>    <li>item-3</ li>    <li>item-4</li>    <li>item-5</li></ul><script>    var lists = document.getElementsByTagName (' Li ');    for (var i = 0; i < lists.length; ++i) {        Lists[i].onclick = (function (i) {                return function () {                  Console.log (" item-"+ (i + 1));                };            }) (i);    }    Add a node    var list = document.getElementById (' list ');    var newNode = document.createelement (' li ');    newnode.innerhtml = "item-6";    List.appendchild (NewNode);</script>
    • The event delegate registration method, which only registers 1 times for content, supports adding elements dynamically:

<ul id= "List" >    <li>item-1</li>    <li>item-2</li>    <li>item-3</ li>    <li>item-4</li>    <li>item-5</li></ul><script>    var list = document.getElementById (' list ');    var handler = function (e) {      e = e | | window.event;      var target = E.target | | e.srcelement;      if (target.nodename && target.nodename = = = "LI") {        console.log (target.innerhtml);      }    };    if (list.addeventlistener) {      list.addeventlistener ("click", Handler);    } else {      list.attachevent (" OnClick ", handler);    }    Add a node    var list = document.getElementById (' list ');    var newNode = document.createelement (' li ');    newnode.innerhtml = "item-6";    List.appendchild (NewNode);</script>

Event Encapsulation

Obviously, the processing of browser compatibility is too troublesome, so here the JS event Registration related functions encapsulated, as a collation.

Both use the Bubbling event model Var myeventutil={//Add Event function addevent:function (Ele, event, func) {var target = Event.target | | even        T.srcelement;        if (Ele.addeventlistener) {Ele.addeventlistener (event, func, false);   } else if (ele.attachevent) {ele.attachevent (' on ' + Event, func);    Func in this is window} else {ele[' on ' + event] = func;            Overwrite}},//delete event function delevent:function (Ele, event, func) {if (Ele.removeeventlistener) {        Ele.removeeventlistener (Event, func, false);        } else if (ele.detachevent) {ele.detachevent (' on ' + Event, func);        } else {ele[' on ' + event] = null;    }},//Gets the source DOM element that triggered the event Getsrcelement:function (event) {return Event.target | | event.srcelement;    },//Get Event Type Gettype:function (event) {return event.type;    },//Get event Getevent:function {return event | | window.event; },//block event bubbling Stoppropagation:fuNction (Event) {if (event.stoppropagation) {event.stoppropagation ();        } else {event.cancelbuble = false; }},//disable default behavior preventdefault:function (event) {if (Event.preventdefault) {Event.preventdefault ()        ;        } else {event.returnvalue = false; }    }};

Events in jquery

It is important to note that the events in jquery work in the bubbling phase and only work in the bubbling phase

Registering, releasing events

    • Method One:

Overrides do not occur, but are not conducive to de-release and cannot be dynamically manipulated event <button id= "button" >here</button>$ ("#button"). Click (function () {   // Register a Click event, and of course you can register other event Console.log ("clicked") with the function of another event name  ;});
    • Method Two:

Does not occur overwrite, facilitates release, cannot dynamically manipulate event <button id= "button" >here</button>//registers an event $ ("#button"). Bind ("click", Function () {    //register a click event, and of course you can register other event Console.log ("clicked") with a function of another event name  ;}); /Of course you can also write this to specify the namespace $ (document) for the event. Bind (' Click.handler1 ', function () {console.log (1);}) $ (document). Bind (' Click.handler2 ', function () {Console.log (2);}) Unlocks an event $ ("#button"). Unbind (". Handler1");    Removes the event $ ("#button") in the Handler1 namespace on the element. Unbind (' Click.handler2 ');   Click.handler2 Event $ ("#button") is lifted on the element. Unbind (' click ');            Unbind all click events on the element $ ("#button"). Unbind ()                    //Unbind all events on the element//bind () method is also subject to 3 parameters form, here do not repeat, interested can see the relevant information.
    • Method Three:

Overwriting does not occur, but is not conducive to de-release, capable of dynamically manipulating events, depending on event bubbling//registering event $ (document). Delegate (". Item", "click", Function () {Console.log ( this.innerhtml);});   The first one is the selector, the second is the event type, and the third is the event function//Remove event $ (document). Undelegate (". Item", "click", handler);  Removes the specified event $ (document) on the element. Undelegate (". Item", "click");  Remove all click events on the Element (document). Undelegate (". Item");  Remove all events on an element
    • Method Four:

Overwrite will not occur, but is not conducive to release, can dynamically manipulate events, does not depend on event bubbling//Registration Event # (". Item"). Live ("Click", Function () {console.log (this.innerhtml);})  The first parameter is the event type, and the second parameter is the event function//Remove event $ (". Item"). Die ("click", handler);  Removes the specified click event on the Element (". Item"). Die ("click");  Remove all click events on an element
    • Two simplified methods:

Hover method $ ("#button"). Hover (function () {        ///mouse-move-in action, not bubbling    }, function () {        //mouse-out action, not bubbling});//toggle method $ ( "#button"). Toggle (function () {        //action on first click    }, Function () {        ////second Click Action}, .../* You can put more than one function, loop response in turn */);

Event triggering

Cannot trigger AddEventListener and attachevent//to actively trigger an event $ ("#button"). Trigger ("click");   Triggers all click events $ ("#button"). Trigger ("Click.handler1");   Triggers all Click.handler1 events $ ("#button"). Trigger (". Handler1");   Event $ ("#button") that triggers all handler1 namespaces. Trigger ("click!");   Triggers the Click event $ ("#button") for all namespaces that do not have a namespace. Trigger (event);   Triggers the same event as Event $ ("#button") on this element. Trigger ({type: "click", Sync:true});   Trigger the Click event, synchronize
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.