In Javasript, proxy and delegate often appear.
So under what circumstances does it actually use? What is its principle?
Here we introduce the usage and principles of javascript delegate, as well as the interface of delegate in frameworks such as Dojo, jQuery, etc.
JavaScript Event Proxy
Event proxying is a very useful and interesting feature in the JS world. When we need to add events to many elements, we can trigger the processing function by adding events to their parent node and delegating events to the parent node.
This is mainly due to the browser's event bubble mechanism. Let's give a specific example to explain how to use this feature.
This example is mainly taken from David Walsh's related articles (How JavaScript Event Delegation Works).
Suppose there is a UL parent node that contains many Li children:
<ul id="list"> <li id="li-1">Li 1</li> <li id="li-2">Li 2</li> <li id="li-3">Li 3</li> <li id="li-4">Li 4</li> <li id="li-5">Li 5</li> </ul>
When our mouse moves to Li, we need to obtain relevant information about this Li and float out of the floating window to display detailed information, or when a Li is clicked, the corresponding processing event needs to be triggered.
Our usual way of writing is to add some event monitoring like onMouseOver or onClick to each Li.
function addListenersLi(liElement) { liElement.onclick = function clickHandler() { //TODO }; liElement.onmouseover = function mouseOverHandler() { //TODO } } window.onload = function() { var ulElement = document.getElementById("list"); var liElements = ulElement.getElementByTagName("Li"); for (var i = liElements.length - 1; i >= 0; i--) { addListenersLi(liElements[i]); } }If the Li child elements in this UL will be added or deleted frequently, we need to call the addListenersLi method every time we add Li to add event handling functions for each Li node.
This can create complexity and possibility of errors in the addition or removal process.
The solution to the problem is to use the event proxy mechanism. When the event is thrown to the parent node of the higher level, we judge and obtain the event source Li by checking the target object of the event.
The following code can achieve the desired effect:
/ Get the parent node and add a click event to it document.getElementById("list").addEventListener("click",function(e) { // Check whether the event source e.targe is Li if(e.target && e.target.nodeName.toUpperCase == "LI") { // //TODO console.log("List item ",e.target.id," was clicked!"); }});Add a click event to the parent node. When the child node is clicked, the click event will bubble upward from the child node. After the parent node catches the event, it determines whether it is the node we need to process by judging e.target.nodeName. And the clicked Li node was obtained through e.target. Therefore, the corresponding information can be obtained and processed.
Event Bubble and Capture
The browser's event bubble mechanism, different browser manufacturers have different processing mechanisms for the capture and handling of events. Here we introduce the standard events defined by W3C for DOM2.0.
The DOM2.0 model divides the event processing process into three stages:
1. Event capture stage,
2. Event target stage,
3. The bubbling stage of event.
As shown in the figure below:
Event capture: When an element triggers an event (such as onclick), the top-level object document will emit an event stream, flowing to the target element node with the node of the DOM tree until the target element where the event actually occurs is reached. In this process, the corresponding listening function of the event will not be triggered.
Event Target: After the target element is reached, the corresponding processing function of the event of the target element is executed. If there is no bound listener function, then it will not be executed.
Event bubbles: Start with the target element and propagate to the top element. If a node binds the corresponding event handling function on the way, these functions will be triggered at once. If you want to prevent the event from bubbled, you can use e.stopPropagation() (Firefox) or e.cancelBubble=true (IE) to organize the bubble spread of the event.
Delegate function in jQuery and Dojo
Let’s take a look at how to use event proxy interfaces provided in Dojo and jQuery.
jQuery:
$("#list").delegate("li", "click", function(){ // "$(this)" is the node that was clicked console.log("you clicked a link!",$(this));});The jQuery delegate method requires three parameters, a selector, a time name, and an event handler.
Dojo's similarity to jQuery is just the difference in programming styles between the two:
require(["dojo/query","dojox/NodeList/delegate"], function(query,delegate){ query("#list").delegate("li","onclick",function(event) { // "this.node" is the node that was clicked console.log("you clicked a link!",this); });})Dojo's delegate module is in dojox.NodeList, and the interface provided is the same as jQuery and the parameters are the same.
Through delegation, you can appreciate the several benefits of using event delegation to development:
1. There are fewer functions managed. There is no need to add a listener function for each element. For similar child elements under the same parent node, events can be handled through a listening function delegated to the parent element.
2. It is easy to add and modify elements dynamically, and there is no need to modify event binding due to element changes.
3. The correlation between JavaScript and DOM nodes is reduced, which reduces the probability of memory leaks caused by circular references.
Using proxy in JavaScript programming
The above introduces the use of the browser bubble mechanism to add event proxy to DOM elements when processing DOM events. In fact, in pure JS programming, we can also use this programming pattern to create proxy objects to operate target objects.
var delegate = function(client, clientMethod) { return function() { return clientMethod.apply(client, arguments); } } var Apple= function() { var _color = "red"; return { getColor: function() { console.log("Color: " + _color); }, setColor: function(color) { _color = color; } }; }; var a = new Apple(); var b = new Apple(); a.getColor(); a.setColor("green"); a.getColor(); //Calling proxy var d = delegate(a, a.setColor); d("blue"); //Execution proxy a.getColor(); //b.getColor();In the above example, the modification of a is operated by calling the proxy function d created by the delegate() function.
Although this method uses apply (call can also be used) to transfer the call object, it implements hiding certain objects from the programming mode, which can protect these objects from being accessed and modified at will.
The concept of delegate is referenced in many frameworks to specify the operation scope of a method.
Typical examples are dojo.hitch(scope, method) and createDelegate(obj,args) of ExtJS.
The above is all about this article, I hope it will be helpful for everyone to learn JavaScript programming.