Learn JS, do not understand event mechanism, basic can say learned JS, is white to learn.


I read a lot of JS related books, evaluation of a said good, I mainly look at two pieces, one is HOW JS object oriented, the other is this event mechanism this piece. Object – oriented press not table, here is the event mechanism in detail.


Event is one of the core things in JS. This is important because JS is an event-driven language.

Talk about the structure of the text. (long, really don’t want to write a series, hope you keep on watching {5 _353:}) about how to bind an event first, say to the event, have to say bubble mechanism, speaking of bubbling mechanism, he said must entrust, say to the event, have to mention the custom event, when it comes to custom events, he said to the observer pattern and release a subscription model. Many books argue that the observer model and the publish/subscribe model are the same thing, and some don’t. I personally tend to agree with the latter. In fact, both patterns (or two names for the same pattern) are essentially delegates (see what I think). AttachEvent,w3c, addEventListener, IE, detachEvent, W3C, removeEventListener, jQuery Live, Delegate, ON, etc., vary from API to API, and vary from API to API due to versioning. I personally always use the same, either bind or on. You can also wrap it yourself. The following code is from JS High Setup,

var EventUtil ={ addHandler: function(element, type, handler){ //w3c if(element.addEventListener){ element.addEventListener(type, handler, false); } //ie else if(element.attachEvent){ element.attachEvent('on' + type,handler); }else{ element['on' + type] = handler; } }, removeHandler: function(){ if(element.removeEventListener){ element.removeEventListener(type, handler, false); }else if(element.detachEvent){ element.detachEvent('on' + type, handler); }else{ element['on' + type] = null; }}}Copy the code


Use the following



var btn = document.getElementById('mybtn');
var handler = function(){
    alert("111")
};
//add click
EventUtil.addHandler(btn, 'click', handler);
//remove click
EventUtil.removeHandler(btn, 'click', handler);
Copy the code


Bubble mechanism and capture mechanism


Ie uses the bubble mechanism, which is supported by w3c.


The third element in the element.addeventListener (type, handler, false) is the capture mechanism, which we usually use to bubble. As for the capture mechanism, I personally have not yet encountered a specific usage scenario.


What about bubbling and capturing?


Look at a situation where the parent element is ul and the child element is Li, and both elements are bound to click events. If we click on Li, of course li’s click event is triggered, is ul triggered? Yes. So there’s a problem. The question of who triggers first.


Bubbling means that the child element’s click event is triggered first, and then the parent element’s click event is triggered from inside out. I don’t think bubbling is a good name. Bubbling gives people the feeling that it spreads from the bottom up. This is based on the DOM tree, which is not very intuitive. Is it better to call the ripple mechanism, because the ripple in the middle is propagated from the inside out.


The trapping mechanism spreads from the outside in (trapping means “catching the net,” or “catching,” you know, with your hands, from the outside in). Click events are triggered for the parent node and then for the child node.


Example 1: Ie 678, click li trigger, pop-up order is Li, ul, document






      
Copy the code


Example 2: Under Chrome, click Li to trigger, and the pop-up sequence is Document,ul,li







ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
}




      
Copy the code


How to prevent bubbling, how to prevent default events is not mentioned here. Jquery has e.topPropagation and e.preventDefault().


3. Event delegation


The core of this article begins.

So before WE say delegate, let’s figure out what’s 94 times 5? So easy, there are two algorithms, the first one (90+4) *5=90*5+4*5=450+20=470. This is normal thinking. The second one is 100 minus 6 times 5 is 500 minus 30 is 470. Psychologically, the second is faster. Why say JS to say well, suddenly calculate a problem. This is mainly a matter of thinking. Maybe our first instinct is to do it the first way. But once we know the second way, it gets faster. It’s not intuitive to say 94 times 5, but if you were to say 99 times 5, almost everyone would do it the second way. The rest of this article is similar to the second method above. Because it’s counterintuitive. But once we do, it’s not a big deal. It is the same as lighting one end of a mosquito coil without breaking it apart. The other end will be left the next day (if it doesn’t work well, that means it is not a good one). (As an aside, I used to use this phrase against interviewers who asked me tough questions. Heh heh.)

Let’s cut the crap and talk about the commission. What is a delegate? You don’t do it yourself. You let someone else do it. A simple example in life is that we shop online, express delivery to the company’s messenger room, and then we go to the messenger room to take a truth. What is the JS delegate? Because of the bubble mechanism, since clicking on the child element also triggers the click event of the parent element. So why don’t we write in the parent element what we’re doing when we click on the child element? Isn’t it a little bit like 500-30? Who came up with it first? I’m impressed. Example 3: use under W3C





      
Copy the code





ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
    margin :5px;
}




      
Copy the code


Example 4 Li’s mouseover and Mouseout events are delegated to the parent node








      
Copy the code





ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
    margin :5px;
}




      
Copy the code


Example 5 Here is another common example. The usage scenario is as follows: We often use tables to display data, and the last column is usually related to data operations, such as view, modify, and delete. You can also use delegates at this point.








      
showDetails update delete
Copy the code






      
showDetails update delete
Copy the code


Ext’s gridPanel does a better job of passing in row click events or table click events. Easy UI is not so good.

Here is a summary of JS delegate correlation. 1. The benefit is great, because the event is bound to the parent node, so there are many fewer events. Even the newly added child nodes naturally have related events. Deleting partials does not require you to destroy the events bound to the corresponding node. 2. The parent node uses event. Target to find the corresponding child node.

How does jquery use delegates? The key to delegation is how to find the corresponding child node from the parent node. You can go to event.target, and if you can get this, you can do whatever you want. Delegates also have a dedicated API. Delegate and on. Target mode, not demo, here is a general on, look at the example. CurrentTarget (currentTarget); currentTarget (currentTarget); Example 6: Write a form to verify that you have done this. This is just a demonstration of the jquery delegate function.




    your name

your age

your sexmale female shemale

submit cancel Copy the code



    your name

your age

your sexmale female shemale

submit cancel Copy the code



Note:CurrentTarget (); currentTarget (); currentTarget (); currentTarget (); currentTarget What’s the difference? Target is the child node that triggered the event in the first place. CurrentTarget is, of course, the current node, the node to which you bind events to execute events. CurrentTarget is the center of the middle layer, while taget is the inner layer. Indicates that the anonymous function was last executed on Center.





#inner{
    width : 200px;
    height:200px;
    cursor : pointer;
    background : gray;
}



      
Copy the code


4. Custom events


How does jquery implement custom events


Jquery uses on or bind to bind custom events and trigger events


The sample



$(function(){
    $('button').on('mycustomEvent',function(){
        alert("trigger customEvent");
    });
    $('button').trigger('mycustomEvent');
});
Copy the code











Copy the code


Here’s how jquery works, and here’s a key thing. I have to explain what a custom event is.


Once you understand it, your JS worldview will change and you’ll feel the whole sky light up (bullshit).


So what is an event? Don’t look for a definition, just close your eyes. The user has to interact with the browser, and the browser has to react. This reaction is the event.


Using the button binding onClick as an example, let’s take a look at the elements that make up the event


First, whose event? Button’s


Second, who triggers, when the user clicks the button triggers the event, so the user triggers it


Third, who executes it? Button executes it, so the corresponding function execution context (execution context) this refers to Button.


Fourth, there is something to be done, and the thing to be done is the execution of the function.


Fifth, since it’s a function, what’s the argument? It’s an event. So what is an event? An event is the state object of an event.


If we are careful, have we found one thing? Function is the most important part of the whole event. Let’s get through the two arteries.

The event == function

Let’s look at the components of the function and just to make it easier, let’s do an example

var obj ={
    fn : function(){
        console.log(this);
        console.log(arguments);
    }
}
obj.fn();
Copy the code


One, whose function? Obj’s


Second, who triggers it, the function call, or the code obj.fn()


Third, who does it? Obj does it, so this of the corresponding function refers to obj.


Fourth, to do something, don’t say,


Fifth, since it is a function, it is unnecessary to say what the parameters are.

The core of this is that triggering is equivalent to calling. Another point of view, events are not to do something, and the function is to do something encapsulation, the two must be involved. So what is a custom event? In a narrow sense, you bind dom elements to events that are not supported by the browser by default. What about in broad terms? If you look at the other side of the equation, the == event function is a custom event

var obj = $('button')
obj.customEvent = function(){
    alert("trigger customEvent");
}
obj.customEvent();Copy the code


But the truth is, it’s not about how the code is written or who has more or less code. It’s a shift in thinking. If you look at functions as events, you look at things differently.


Js is an event-driven language. Now I can understand this sentence better.

Anyway, back to jquery custom events. Let’s take a look at the full selection example, so we can see how it works. Here’s how intuitive thinking works.





body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


The core code is


To achieve 1:


$(function () {/ / bind button click event $(' # add ') on (' click ', function () {/ / see if all the if ($(' # selectAll.) is (' checked ')) { $('#container').append('');
        }else{
            $('#container').append(' '); }}); / / all logic $(' # selectAll.) on (' click ', function () {if (this. Checked) { $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); }}); })Copy the code


You can see it up here


Add works with Containers and selectAll


SelectAll deals with containers


If you think of these three as three modules, you can say that these three are strongly coupled.

Add and selectAll interact with container. Implement 2

$(function(){ var $container =$('#container'); $container. On ('selectCheckbox',function(e,checked){var this = $(this).data('state',checked); if(checked){ $this.find('input:checkbox').prop('checked','checked'); }else{ $this.find('input:checkbox').removeProp('checked'); } }).on('addCheckbox',function(){ var $this = $(this); if($this.data('state')){ $this.append('');
        }else{
            $this.append(' '); }}); $('#selectAll').on('click',function(){$container.trigger('selectCheckbox',[this.checked])}); $('#add'). On ('click',function(){$container.trigger('addCheckbox'); }); })Copy the code


Better yet, not completely, could the three modules not be coupled at all?


It may seem difficult, but one more module would be fine. (In this case, there is more code than the original implementation.


Implement 3


$(function(){ var $common =$({}); $common.on('selectCheckbox',function(e,checked){var $this = $(this).data('state',checked); if(checked){ $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); } }).on('addCheckbox',function(){ if($(this).data('state')){ $('#container').append('');
        }else{
            $('#container').append(' '); }}); $('#selectAll').on('click',function(){$common.trigger('selectCheckbox',[this.checked])}); $('#add').on('click',function(){$common.trigger('addCheckbox'); }); })Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


If the requirements change, the reverse selection is also implemented, i.e., if only one of the requirements is not selected, the selectAll must become unselected, and all of the container must be selected, and the selectAll must also be selected. The third logic should be the easiest to change. It’s decoupled.

Now let’s try to get through this binary component interaction == callback function == bind event == event listener == call method == pass message

I picked that example and I kept saying three if it’s three modules, what if it’s three modules? Let’s see if WE can really think of a function as an event





body{
    margin : 30px;
}
.container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}










Copy the code




body{
    margin : 30px;
}
.container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}










Copy the code

Before we talk about publish-subscribe mode, let’s look at delegation again. Now I’m talking about delegates, not just delegates because of the bubbling mechanism. We want to stand in a higher level to study this thing (is the so-called standing high urine far, hey hey). What is the nature of delegation? Again, what you need to do is not to do it yourself, but to ask others to do it. Well, since the guest of honor is different, this leads to two ideas. When I delegate, IT’s like I borrow a chicken to lay eggs. (Intuitive thinking) When someone entrusts me, it’s like I’m making someone else’s wedding clothes. So let’s see how to do the wedding dress, how to lay eggs

var sum = function(a, b){ return a + b; } var mysum = function(a, b){ return sum(a, b); } alert (mysum (2, 3));Copy the code


Mysum uses Sum to lay eggs.


At this time, you may say, “Lao Yao, I have little education, don’t fool me.” It’s just a simple function call that has nothing to do with delegates.


Yes, this is a function call, but we’re going to look at our code from the perspective of a delegate, and we might think differently depending on the perspective.


Just to keep going, let’s make it a little bit more complicated


var operation = function(a,b,oper){ var r = 0 switch(oper){ case '+': r = a+b; break; case '-': r = a-b; break; case '*': r = a*b; break; case '/': r = a/b; break; case '%': r = a%b; break; default : r = NAN; } return r; } var minus = function(a,b){ return operation(a,b,'-'); } alert (minus (4, 2));Copy the code


It can be said that operation is to make wedding clothes for minus. Simple as the code is, this is a pattern: facade pattern.


You said that we should use operation to subtract. Of course, it is ok. But minus is simpler and more semantic.


Jquery makes a lot of use of this method. On is the front of bind, $. Get is the front of $. Ajax, etc.

When we’re working on a project, when we start to write code, before we have a complete understanding of the function, we’re basically thinking about how to use the previous function. This is understandable. After all the functions are done, don’t think the job is done. One more thing to do is refactor. The idea of reconstruction is the opposite, is to think of ways to do a variety of wedding clothes. There is another case where laying eggs and getting married are the same thing. Can you guess what it is? Recursion. Recursion is as simple as it is difficult. I spent a lot of time on recursion, and I may write an article about it in the future. Writing articles is actually for others to do wedding clothes. We study, of course, is to borrow the chicken to lay eggs. You see, the concept of delegation can rise to a philosophical level at will.

Anyway, keep laying eggs.

var P = function(name){
    this.name = name;
}

var Man = function(name,sex){
    P.call(this,name);
    this.sex = sex;
}

var m = new Man('laoyao','male');
alert(m.name);Copy the code


This is a simple implementation of class inheritance. Man = this.name = name, Man = this.name = name, Man = this.name = name


The event delegate is bubbling, what about the function delegate? If you want to change your this to mine, call and apply.


Arguments are pseudo-arrays. To become real arrays, we need to write some logic. The result is similar to the basic logic inside the array’s slice.


Well, when you’re done, I’ll stop. I can just delegate it to you. [].slice.call(arguments,0); (Of course, THIS is an afterthought, I don’t see how others use it.)


Component to component communication, how to interact, is there any delegate? Yes, you guessed it, publish and subscribe.


Remember the all-select example, where there was an implementation (implementation 3) that decoupled the modules enough to fill in a new module, $common. Yes, that’s the socket through which everyone communicates.


The publish-subscribe model has gone so far that we don’t even know it exists.


Let’s see how it works.


(function($){
    var o = $({});
    $.sub = function(){
        o.on.apply(o,arguments);
    }
    $.unsub = function(){
        o.off.apply(o,arguments);
    }
    $.pub = function(){
        o.trigger.apply(o,arguments);
    }
})(jQuery);Copy the code


Use as follows:


$.sub('customEvent',function(e,text){
    alert(text);
})
$.pub('customEvent',['oh yeah']);
$.pub('customEvent',['haha']);
$.unsub('customEvent');
$.pub('customEvent',['can not see']);Copy the code


Run as follows:










Copy the code


Let’s take a quick look at those lines of code


Add three static functions to jQuery: Subscribe, unsubscribe, and publish. Functions are implemented internally via on and trigger. Delegate to the object $({}).


Internally though, this is done by binding custom events and firing custom events. Custom events are just a name. We can officially think of it as a channel or a theme, subscribe to my theme, and you’ll see it when I tweet.


Let’s change the implementation 3 example of universal selection.


Implement 5


$(function(){ var currentChecked = false; $.sub('selectCheckbox',function(e,checked){currentChecked = checked; if(checked){ $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); $.sub('addCheckbox',function(){if(currentChecked){$('#container').append(');
        }else{
            $('#container').append(' '); }}); / / selection button $(' # selectAll). Posting on (' click ', function () {$. Pub (' selectCheckbox, [this. Checked])}); / / new button released subject $(' # add '). On (' click ', function () {$. Pub (' addCheckbox '); }); })Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


Similarly, we can rewrite the Controller layer of implementation 4 for all options


$(function(){var currentChecked = false; $.sub('selectAll',function(e,flag){ currentChecked = flag; container.selectOrCacelAll(flag); }); $.sub('addBox',function(e){ container.add(currentChecked); }); Var selectAll = new selectAll ({listeners: {onSelectAll :function(flag){$.pub('selectAll',[flag]); }}}); Var listeners = new add ({listeners: {onAdd: function(){$.pub(' listeners '); }}}); Var container = new container ({}); });Copy the code


Native JS implementation, there are many kinds of implementation methods, here I simply wrote a, anonymous function or delete can not be removed (if you want to implement it, have to get a UID just line).


var obj = (function(){ return { topics : {}, sub : function(topic,fn){ if(! this.topics[topic]){ this.topics[topic] = []; } this.topics[topic].push(fn); }, pub : function(topic){ var arr = this.topics[topic]; var args = [].slice.call(arguments,1); if(! arr){ return; } for(var i = 0, len = arr.length; i < len; i++){ arr[i](args); } }, unsub : function(topic,fn){ var arr = this.topics[topic]; if(! arr){ return; } if(typeof fn ! == 'function'){ delete this.topics[topic]; return; } for(var i = 0, len = arr.length; i < len; i++){ if(arr[i] == fn){ arr.splice(i,1); }}}}; }) ();Copy the code











Copy the code


6. Observer model


What can you think of when you say Observer?


The first thing I thought of was the big bald guy from Fringe, who was watching every major historical event happen.


Few people think directly of browsers. In fact, our browser is an observer mode.

A few concepts: if you say the observer model, there must be an observer, and who to observe, the observed, let’s call it the target. To observe your what? Good looking? You’re looking at states. What am I watching you do, see if you’ve changed? Do my job according to your condition.

For example: Target: select all check boxes Observer: Select all check boxes in Container, and Add status: Select all action: Select Container, I select Container, click Add, add the selected button, and vice versa.

So how do you do that? There are two ways of thinking about it: I watch you, I want to see how you’re doing, I can go to you and see, and the other way is you tell me when your state changes. To put it bluntly, it is the concept of “taking” and “giving”. The observer model uses the concept of “send”. That also raises the question, since it is “send”, how can you find me? Then you need to save the address I gave you.

Now we can look at the definition. Observer: Defines a one-to-many dependency between objects so that when an object’s state changes, all dependent objects are notified and refreshed automatically. Ok, so let’s just implement it that way. Implement 6

$(function(){var $selectAll = $('#selectAll'); var $add = $('#add'); var $container = $('#container'); $selectall.cblist = []; $selectAll.addBtn = $add; // Target notification function, $selectall. notify = function(value){$.each(this.cblist,function(index,checkbox){checkbox.update(value); }); this.addBtn.update(value); }; $selectAll.click(function(){ $selectAll.notify(this.checked); }) $add.click(function(){ addCheckbox($add.data('checked')); }); $add.update = function(value){this.data('checked',value); } function addCheckbox(flag){ var $cb; if(flag){ $cb = $('');
        }else{
            $cb = $(''); $cb.update = function(value){this[0]. Checked = value; } $selectAll.cblist.push ($cb); $('#container').append($cb); }})Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}





 add

      
Copy the code


Looking at this, it’s hard to avoid thinking that there is no shadow of the observer pattern.


The next step is to extract the abstract interface of the target and observer, and then the actual observed pattern can be reused.


var ObserverPatten = (function(){ var Subject = function(){ this.observerlist = []; }; Subject.prototype = { add : function(observer){ this.observerlist.push(observer); }, notify : function(state){ var arr = this.observerlist; for(var i = 0, len = arr.length; iCopy the code


So the full selection example could be changed to the following


Realization of 7


$(function(){var $selectAll = $('#selectAll'); var $add = $('#add'); var $container = $('#container'); $selectAll.extend(new observerpatten.subject); $selectAll.add($add); $selectAll.click(function(){ $selectAll.notify(this.checked); }) $add.click(function(){ addCheckbox($add.data('checked')); }); // Observer add implements Observer interface $add.extend(new observerpatten.observer); $add.update = function(value){this.data('checked',value); } function addCheckbox(flag){ var $cb; if(flag){ $cb = $('');
        }else{
            $cb = $(''); } // Observer check box implements Observer interface $cb.extend(new observerpatten.observer); $cb.update = function(value){this[0]. Checked = value; } // Target saves observer $selectall.add ($cb); $('#container').append($cb); }})Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


Seven, afterword.


I’ve been writing here for a week, and I haven’t finished. It’s really long.


Reviewing this article, the main thing is to deliberately blur the distinction between events and functions in our minds. The goal is just to make it easier for us to understand the code.


As for the publish and subscribe mode and the observer mode, it is only a general talk about the issue of subscription mode in the full selection of this example, in fact, is a special case, is the intermediary mode.


A subscriber can also act as a publisher of another subscriber. So publishers and subscribers can be many-to-many.


As for sending orders, it is understandable that they are a branch of the observer. All three modules are observers, and the goal is to publish $({}) in the subscription implementation.


This thing, originally intended to expand, intended to write many-to-many examples. This article is too long to read.


Writing an article is really not easy, not only to consider the words out, there is no ambiguity. I have to take responsibility for my own words. Try not to offend your children.


There is another thing, more troublesome. Is the design of the case, but also try not to copy similar online articles, so that others say you copy. It’s a headache.


There are actually a couple of other points that I wanted to expand on. Read in the eyebrows beard, no focus, leave it to the future.


In this paper, to the end.


Learn JS, do not understand event mechanism, basic can say learned JS, is white to learn.


I read a lot of JS related books, evaluation of a said good, I mainly look at two pieces, one is HOW JS object oriented, the other is this event mechanism this piece. Object – oriented press not table, here is the event mechanism in detail.


Event is one of the core things in JS. This is important because JS is an event-driven language.

Talk about the structure of the text. (long, really don’t want to write a series, hope you keep on watching {5 _353:}) about how to bind an event first, say to the event, have to say bubble mechanism, speaking of bubbling mechanism, he said must entrust, say to the event, have to mention the custom event, when it comes to custom events, he said to the observer pattern and release a subscription model. Many books argue that the observer model and the publish/subscribe model are the same thing, and some don’t. I personally tend to agree with the latter. In fact, both patterns (or two names for the same pattern) are essentially delegates (see what I think). AttachEvent,w3c, addEventListener, IE, detachEvent, W3C, removeEventListener, jQuery Live, Delegate, ON, etc., vary from API to API, and vary from API to API due to versioning. I personally always use the same, either bind or on. You can also wrap it yourself. The following code is from JS High Setup,

var EventUtil ={ addHandler: function(element, type, handler){ //w3c if(element.addEventListener){ element.addEventListener(type, handler, false); } //ie else if(element.attachEvent){ element.attachEvent('on' + type,handler); }else{ element['on' + type] = handler; } }, removeHandler: function(){ if(element.removeEventListener){ element.removeEventListener(type, handler, false); }else if(element.detachEvent){ element.detachEvent('on' + type, handler); }else{ element['on' + type] = null; }}}Copy the code


Use the following



var btn = document.getElementById('mybtn');
var handler = function(){
    alert("111")
};
//add click
EventUtil.addHandler(btn, 'click', handler);
//remove click
EventUtil.removeHandler(btn, 'click', handler);
Copy the code


Bubble mechanism and capture mechanism


Ie uses the bubble mechanism, which is supported by w3c.


The third element in the element.addeventListener (type, handler, false) is the capture mechanism, which we usually use to bubble. As for the capture mechanism, I personally have not yet encountered a specific usage scenario.


What about bubbling and capturing?


Look at a situation where the parent element is ul and the child element is Li, and both elements are bound to click events. If we click on Li, of course li’s click event is triggered, is ul triggered? Yes. So there’s a problem. The question of who triggers first.


Bubbling means that the child element’s click event is triggered first, and then the parent element’s click event is triggered from inside out. I don’t think bubbling is a good name. Bubbling gives people the feeling that it spreads from the bottom up. This is based on the DOM tree, which is not very intuitive. Is it better to call the ripple mechanism, because the ripple in the middle is propagated from the inside out.


The trapping mechanism spreads from the outside in (trapping means “catching the net,” or “catching,” you know, with your hands, from the outside in). Click events are triggered for the parent node and then for the child node.


Example 1: Ie 678, click li trigger, pop-up order is Li, ul, document






      
Copy the code


Example 2: Under Chrome, click Li to trigger, and the pop-up sequence is Document,ul,li







ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
}




      
Copy the code


How to prevent bubbling, how to prevent default events is not mentioned here. Jquery has e.topPropagation and e.preventDefault().


3. Event delegation


The core of this article begins.

So before WE say delegate, let’s figure out what’s 94 times 5? So easy, there are two algorithms, the first one (90+4) *5=90*5+4*5=450+20=470. This is normal thinking. The second one is 100 minus 6 times 5 is 500 minus 30 is 470. Psychologically, the second is faster. Why say JS to say well, suddenly calculate a problem. This is mainly a matter of thinking. Maybe our first instinct is to do it the first way. But once we know the second way, it gets faster. It’s not intuitive to say 94 times 5, but if you were to say 99 times 5, almost everyone would do it the second way. The rest of this article is similar to the second method above. Because it’s counterintuitive. But once we do, it’s not a big deal. It is the same as lighting one end of a mosquito coil without breaking it apart. The other end will be left the next day (if it doesn’t work well, that means it is not a good one). (As an aside, I used to use this phrase against interviewers who asked me tough questions. Heh heh.)

Let’s cut the crap and talk about the commission. What is a delegate? You don’t do it yourself. You let someone else do it. A simple example in life is that we shop online, express delivery to the company’s messenger room, and then we go to the messenger room to take a truth. What is the JS delegate? Because of the bubble mechanism, since clicking on the child element also triggers the click event of the parent element. So why don’t we write in the parent element what we’re doing when we click on the child element? Isn’t it a little bit like 500-30? Who came up with it first? I’m impressed. Example 3: use under W3C





      
Copy the code





ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
    margin :5px;
}




      
Copy the code


Example 4 Li’s mouseover and Mouseout events are delegated to the parent node








      
Copy the code





ul{
    background : gray;
    padding : 20px;
}
ul li{
    background : green;
    margin :5px;
}




      
Copy the code


Example 5 Here is another common example. The usage scenario is as follows: We often use tables to display data, and the last column is usually related to data operations, such as view, modify, and delete. You can also use delegates at this point.








      
showDetails update delete
Copy the code






      
showDetails update delete
Copy the code


Ext’s gridPanel does a better job of passing in row click events or table click events. Easy UI is not so good.

Here is a summary of JS delegate correlation. 1. The benefit is great, because the event is bound to the parent node, so there are many fewer events. Even the newly added child nodes naturally have related events. Deleting partials does not require you to destroy the events bound to the corresponding node. 2. The parent node uses event. Target to find the corresponding child node.

How does jquery use delegates? The key to delegation is how to find the corresponding child node from the parent node. You can go to event.target, and if you can get this, you can do whatever you want. Delegates also have a dedicated API. Delegate and on. Target mode, not demo, here is a general on, look at the example. CurrentTarget (currentTarget); currentTarget (currentTarget); Example 6: Write a form to verify that you have done this. This is just a demonstration of the jquery delegate function.




    your name

your age

your sexmale female shemale

submit cancel Copy the code



    your name

your age

your sexmale female shemale

submit cancel Copy the code



Note:CurrentTarget (); currentTarget (); currentTarget (); currentTarget (); currentTarget What’s the difference? Target is the child node that triggered the event in the first place. CurrentTarget is, of course, the current node, the node to which you bind events to execute events. CurrentTarget is the center of the middle layer, while taget is the inner layer. Indicates that the anonymous function was last executed on Center.





#inner{
    width : 200px;
    height:200px;
    cursor : pointer;
    background : gray;
}



      
Copy the code


4. Custom events


How does jquery implement custom events


Jquery uses on or bind to bind custom events and trigger events


The sample



$(function(){
    $('button').on('mycustomEvent',function(){
        alert("trigger customEvent");
    });
    $('button').trigger('mycustomEvent');
});
Copy the code











Copy the code


Here’s how jquery works, and here’s a key thing. I have to explain what a custom event is.


Once you understand it, your JS worldview will change and you’ll feel the whole sky light up (bullshit).


So what is an event? Don’t look for a definition, just close your eyes. The user has to interact with the browser, and the browser has to react. This reaction is the event.


Using the button binding onClick as an example, let’s take a look at the elements that make up the event


First, whose event? Button’s


Second, who triggers, when the user clicks the button triggers the event, so the user triggers it


Third, who executes it? Button executes it, so the corresponding function execution context (execution context) this refers to Button.


Fourth, there is something to be done, and the thing to be done is the execution of the function.


Fifth, since it’s a function, what’s the argument? It’s an event. So what is an event? An event is the state object of an event.


If we are careful, have we found one thing? Function is the most important part of the whole event. Let’s get through the two arteries.

The event == function

Let’s look at the components of the function and just to make it easier, let’s do an example

var obj ={
    fn : function(){
        console.log(this);
        console.log(arguments);
    }
}
obj.fn();
Copy the code


One, whose function? Obj’s


Second, who triggers it, the function call, or the code obj.fn()


Third, who does it? Obj does it, so this of the corresponding function refers to obj.


Fourth, to do something, don’t say,


Fifth, since it is a function, it is unnecessary to say what the parameters are.

The core of this is that triggering is equivalent to calling. Another point of view, events are not to do something, and the function is to do something encapsulation, the two must be involved. So what is a custom event? In a narrow sense, you bind dom elements to events that are not supported by the browser by default. What about in broad terms? If you look at the other side of the equation, the == event function is a custom event

var obj = $('button')
obj.customEvent = function(){
    alert("trigger customEvent");
}
obj.customEvent();Copy the code


But the truth is, it’s not about how the code is written or who has more or less code. It’s a shift in thinking. If you look at functions as events, you look at things differently.


Js is an event-driven language. Now I can understand this sentence better.

Anyway, back to jquery custom events. Let’s take a look at the full selection example, so we can see how it works. Here’s how intuitive thinking works.





body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


The core code is


To achieve 1:


$(function () {/ / bind button click event $(' # add ') on (' click ', function () {/ / see if all the if ($(' # selectAll.) is (' checked ')) { $('#container').append('');
        }else{
            $('#container').append(' '); }}); / / all logic $(' # selectAll.) on (' click ', function () {if (this. Checked) { $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); }}); })Copy the code


You can see it up here


Add works with Containers and selectAll


SelectAll deals with containers


If you think of these three as three modules, you can say that these three are strongly coupled.

Add and selectAll interact with container. Implement 2

$(function(){ var $container =$('#container'); $container. On ('selectCheckbox',function(e,checked){var this = $(this).data('state',checked); if(checked){ $this.find('input:checkbox').prop('checked','checked'); }else{ $this.find('input:checkbox').removeProp('checked'); } }).on('addCheckbox',function(){ var $this = $(this); if($this.data('state')){ $this.append('');
        }else{
            $this.append(' '); }}); $('#selectAll').on('click',function(){$container.trigger('selectCheckbox',[this.checked])}); $('#add'). On ('click',function(){$container.trigger('addCheckbox'); }); })Copy the code


Better yet, not completely, could the three modules not be coupled at all?


It may seem difficult, but one more module would be fine. (In this case, there is more code than the original implementation.


Implement 3


$(function(){ var $common =$({}); $common.on('selectCheckbox',function(e,checked){var $this = $(this).data('state',checked); if(checked){ $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); } }).on('addCheckbox',function(){ if($(this).data('state')){ $('#container').append('');
        }else{
            $('#container').append(' '); }}); $('#selectAll').on('click',function(){$common.trigger('selectCheckbox',[this.checked])}); $('#add').on('click',function(){$common.trigger('addCheckbox'); }); })Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


If the requirements change, the reverse selection is also implemented, i.e., if only one of the requirements is not selected, the selectAll must become unselected, and all of the container must be selected, and the selectAll must also be selected. The third logic should be the easiest to change. It’s decoupled.

Now let’s try to get through this binary component interaction == callback function == bind event == event listener == call method == pass message

I picked that example and I kept saying three if it’s three modules, what if it’s three modules? Let’s see if WE can really think of a function as an event





body{
    margin : 30px;
}
.container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}










Copy the code




body{
    margin : 30px;
}
.container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}










Copy the code

Before we talk about publish-subscribe mode, let’s look at delegation again. Now I’m talking about delegates, not just delegates because of the bubbling mechanism. We want to stand in a higher level to study this thing (is the so-called standing high urine far, hey hey). What is the nature of delegation? Again, what you need to do is not to do it yourself, but to ask others to do it. Well, since the guest of honor is different, this leads to two ideas. When I delegate, IT’s like I borrow a chicken to lay eggs. (Intuitive thinking) When someone entrusts me, it’s like I’m making someone else’s wedding clothes. So let’s see how to do the wedding dress, how to lay eggs

var sum = function(a, b){ return a + b; } var mysum = function(a, b){ return sum(a, b); } alert (mysum (2, 3));Copy the code


Mysum uses Sum to lay eggs.


At this time, you may say, “Lao Yao, I have little education, don’t fool me.” It’s just a simple function call that has nothing to do with delegates.


Yes, this is a function call, but we’re going to look at our code from the perspective of a delegate, and we might think differently depending on the perspective.


Just to keep going, let’s make it a little bit more complicated


var operation = function(a,b,oper){ var r = 0 switch(oper){ case '+': r = a+b; break; case '-': r = a-b; break; case '*': r = a*b; break; case '/': r = a/b; break; case '%': r = a%b; break; default : r = NAN; } return r; } var minus = function(a,b){ return operation(a,b,'-'); } alert (minus (4, 2));Copy the code


It can be said that operation is to make wedding clothes for minus. Simple as the code is, this is a pattern: facade pattern.


You said that we should use operation to subtract. Of course, it is ok. But minus is simpler and more semantic.


Jquery makes a lot of use of this method. On is the front of bind, $. Get is the front of $. Ajax, etc.

When we’re working on a project, when we start to write code, before we have a complete understanding of the function, we’re basically thinking about how to use the previous function. This is understandable. After all the functions are done, don’t think the job is done. One more thing to do is refactor. The idea of reconstruction is the opposite, is to think of ways to do a variety of wedding clothes. There is another case where laying eggs and getting married are the same thing. Can you guess what it is? Recursion. Recursion is as simple as it is difficult. I spent a lot of time on recursion, and I may write an article about it in the future. Writing articles is actually for others to do wedding clothes. We study, of course, is to borrow the chicken to lay eggs. You see, the concept of delegation can rise to a philosophical level at will.

Anyway, keep laying eggs.

var P = function(name){
    this.name = name;
}

var Man = function(name,sex){
    P.call(this,name);
    this.sex = sex;
}

var m = new Man('laoyao','male');
alert(m.name);Copy the code


This is a simple implementation of class inheritance. Man = this.name = name, Man = this.name = name, Man = this.name = name


The event delegate is bubbling, what about the function delegate? If you want to change your this to mine, call and apply.


Arguments are pseudo-arrays. To become real arrays, we need to write some logic. The result is similar to the basic logic inside the array’s slice.


Well, when you’re done, I’ll stop. I can just delegate it to you. [].slice.call(arguments,0); (Of course, THIS is an afterthought, I don’t see how others use it.)


Component to component communication, how to interact, is there any delegate? Yes, you guessed it, publish and subscribe.


Remember the all-select example, where there was an implementation (implementation 3) that decoupled the modules enough to fill in a new module, $common. Yes, that’s the socket through which everyone communicates.


The publish-subscribe model has gone so far that we don’t even know it exists.


Let’s see how it works.


(function($){
    var o = $({});
    $.sub = function(){
        o.on.apply(o,arguments);
    }
    $.unsub = function(){
        o.off.apply(o,arguments);
    }
    $.pub = function(){
        o.trigger.apply(o,arguments);
    }
})(jQuery);Copy the code


Use as follows:


$.sub('customEvent',function(e,text){
    alert(text);
})
$.pub('customEvent',['oh yeah']);
$.pub('customEvent',['haha']);
$.unsub('customEvent');
$.pub('customEvent',['can not see']);Copy the code


Run as follows:










Copy the code


Let’s take a quick look at those lines of code


Add three static functions to jQuery: Subscribe, unsubscribe, and publish. Functions are implemented internally via on and trigger. Delegate to the object $({}).


Internally though, this is done by binding custom events and firing custom events. Custom events are just a name. We can officially think of it as a channel or a theme, subscribe to my theme, and you’ll see it when I tweet.


Let’s change the implementation 3 example of universal selection.


Implement 5


$(function(){ var currentChecked = false; $.sub('selectCheckbox',function(e,checked){currentChecked = checked; if(checked){ $('#container').find('input:checkbox').prop('checked','checked'); }else{ $('#container').find('input:checkbox').removeProp('checked'); $.sub('addCheckbox',function(){if(currentChecked){$('#container').append(');
        }else{
            $('#container').append(' '); }}); / / selection button $(' # selectAll). Posting on (' click ', function () {$. Pub (' selectCheckbox, [this. Checked])}); / / new button released subject $(' # add '). On (' click ', function () {$. Pub (' addCheckbox '); }); })Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


Similarly, we can rewrite the Controller layer of implementation 4 for all options


$(function(){var currentChecked = false; $.sub('selectAll',function(e,flag){ currentChecked = flag; container.selectOrCacelAll(flag); }); $.sub('addBox',function(e){ container.add(currentChecked); }); Var selectAll = new selectAll ({listeners: {onSelectAll :function(flag){$.pub('selectAll',[flag]); }}}); Var listeners = new add ({listeners: {onAdd: function(){$.pub(' listeners '); }}}); Var container = new container ({}); });Copy the code


Native JS implementation, there are many kinds of implementation methods, here I simply wrote a, anonymous function or delete can not be removed (if you want to implement it, have to get a UID just line).


var obj = (function(){ return { topics : {}, sub : function(topic,fn){ if(! this.topics[topic]){ this.topics[topic] = []; } this.topics[topic].push(fn); }, pub : function(topic){ var arr = this.topics[topic]; var args = [].slice.call(arguments,1); if(! arr){ return; } for(var i = 0, len = arr.length; i < len; i++){ arr[i](args); } }, unsub : function(topic,fn){ var arr = this.topics[topic]; if(! arr){ return; } if(typeof fn ! == 'function'){ delete this.topics[topic]; return; } for(var i = 0, len = arr.length; i < len; i++){ if(arr[i] == fn){ arr.splice(i,1); }}}}; }) ();Copy the code











Copy the code


6. Observer model


What can you think of when you say Observer?


The first thing I thought of was the big bald guy from Fringe, who was watching every major historical event happen.


Few people think directly of browsers. In fact, our browser is an observer mode.

A few concepts: if you say the observer model, there must be an observer, and who to observe, the observed, let’s call it the target. To observe your what? Good looking? You’re looking at states. What am I watching you do, see if you’ve changed? Do my job according to your condition.

For example: Target: select all check boxes Observer: Select all check boxes in Container, and Add status: Select all action: Select Container, I select Container, click Add, add the selected button, and vice versa.

So how do you do that? There are two ways of thinking about it: I watch you, I want to see how you’re doing, I can go to you and see, and the other way is you tell me when your state changes. To put it bluntly, it is the concept of “taking” and “giving”. The observer model uses the concept of “send”. That also raises the question, since it is “send”, how can you find me? Then you need to save the address I gave you.

Now we can look at the definition. Observer: Defines a one-to-many dependency between objects so that when an object’s state changes, all dependent objects are notified and refreshed automatically. Ok, so let’s just implement it that way. Implement 6

$(function(){var $selectAll = $('#selectAll'); var $add = $('#add'); var $container = $('#container'); $selectall.cblist = []; $selectAll.addBtn = $add; // Target notification function, $selectall. notify = function(value){$.each(this.cblist,function(index,checkbox){checkbox.update(value); }); this.addBtn.update(value); }; $selectAll.click(function(){ $selectAll.notify(this.checked); }) $add.click(function(){ addCheckbox($add.data('checked')); }); $add.update = function(value){this.data('checked',value); } function addCheckbox(flag){ var $cb; if(flag){ $cb = $('');
        }else{
            $cb = $(''); $cb.update = function(value){this[0]. Checked = value; } $selectAll.cblist.push ($cb); $('#container').append($cb); }})Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}





 add

      
Copy the code


Looking at this, it’s hard to avoid thinking that there is no shadow of the observer pattern.


The next step is to extract the abstract interface of the target and observer, and then the actual observed pattern can be reused.


var ObserverPatten = (function(){ var Subject = function(){ this.observerlist = []; }; Subject.prototype = { add : function(observer){ this.observerlist.push(observer); }, notify : function(state){ var arr = this.observerlist; for(var i = 0, len = arr.length; iCopy the code


So the full selection example could be changed to the following


Realization of 7


$(function(){var $selectAll = $('#selectAll'); var $add = $('#add'); var $container = $('#container'); $selectAll.extend(new observerpatten.subject); $selectAll.add($add); $selectAll.click(function(){ $selectAll.notify(this.checked); }) $add.click(function(){ addCheckbox($add.data('checked')); }); // Observer add implements Observer interface $add.extend(new observerpatten.observer); $add.update = function(value){this.data('checked',value); } function addCheckbox(flag){ var $cb; if(flag){ $cb = $('');
        }else{
            $cb = $(''); } // Observer check box implements Observer interface $cb.extend(new observerpatten.observer); $cb.update = function(value){this[0]. Checked = value; } // Target saves observer $selectall.add ($cb); $('#container').append($cb); }})Copy the code




body{
    margin : 30px;
}
#container{
    border : 1px solid black;
    width : 200px;
    height :200px;
}






 add

      
Copy the code


Seven, afterword.


I’ve been writing here for a week, and I haven’t finished. It’s really long.


Reviewing this article, the main thing is to deliberately blur the distinction between events and functions in our minds. The goal is just to make it easier for us to understand the code.


As for the publish and subscribe mode and the observer mode, it is only a general talk about the issue of subscription mode in the full selection of this example, in fact, is a special case, is the intermediary mode.


A subscriber can also act as a publisher of another subscriber. So publishers and subscribers can be many-to-many.


As for sending orders, it is understandable that they are a branch of the observer. All three modules are observers, and the goal is to publish $({}) in the subscription implementation.


This thing, originally intended to expand, intended to write many-to-many examples. This article is too long to read.


Writing an article is really not easy, not only to consider the words out, there is no ambiguity. I have to take responsibility for my own words. Try not to offend your children.


There is another thing, more troublesome. Is the design of the case, but also try not to copy similar online articles, so that others say you copy. It’s a headache.


There are actually a couple of other points that I wanted to expand on. Read in the eyebrows beard, no focus, leave it to the future.


In this paper, to the end.