📜 ⬆️ ⬇️

Hands-on experience creating Dojo widgets. Optimize javascript code performance

Good day, habrasoobschestvo.

I want to share with you some useful, in my opinion, information that will be of interest to those who are developing or planning to start developing their Dojo widgets. I want to immediately warn you that in this article I will not tell you how to gradually create your own Dojo widget (however, if the community is interested in this topic, I hope to present it in a separate article). Instead, I want to highlight the main points and principles that everyone who is involved in developing Dojo widgets or has anything to do with this topic should know and take into account.

image
')
image


Dojo widgets


I think it would not be superfluous to say a few words about the concept of widgets.
The goal of the Dojo widgets is to encapsulate visual Web components for repeated reuse. The Dojo widget is handled on the web browser side.
The structure of the Dojo widgets is independent of the structure of the DOM objects. Each Dojo widget has a unique widgetId and may contain none, or it may contain one or more DOM elements, as well as Dojo child widgets.

A widget consists of several files. A javascript file is required, while others are optional:

Practical experience in creating widgets.


Software and declarative models for creating Dojo widgets

Dojo allows us to create widgets in two ways: declaratively and programmatically.
Programmatically, we can instantiate a widget using JavaScript code:
var myWidget = new WidgetClass({ //properties },”targetNode”); * This source code was highlighted with Source Code Highlighter .
  1. var myWidget = new WidgetClass({ //properties },”targetNode”); * This source code was highlighted with Source Code Highlighter .
  2. var myWidget = new WidgetClass({ //properties },”targetNode”); * This source code was highlighted with Source Code Highlighter .
  3. var myWidget = new WidgetClass({ //properties },”targetNode”); * This source code was highlighted with Source Code Highlighter .
var myWidget = new WidgetClass({ //properties },”targetNode”); * This source code was highlighted with Source Code Highlighter .

Declaratively widgets are created directly via markup:
  1. < div dojoType = “ WidgetClass ” > </ div >
* This source code was highlighted with Source Code Highlighter .

Declarative declared widgets will be detected and instantiated by the dojo parser immediately after the body.load event and before calling the functions from dojo.addOnLoad . Therefore, in order not to block the flow of execution, it is best to postpone the execution of resource-intensive tasks to addOnLoad wherever possible.
  1. < div dojoType = “ myWidgetClass ” postCreate = “ slowFunction ” > </ div >
  2. // Slow option:
  3. slowFunction () {doSlowStuff ();}
  4. // Optimized version:
  5. slowFunction () {dojo.addOnLoad (doSlowStuff ());}
* This source code was highlighted with Source Code Highlighter .

The developers of Dojo clearly have a description of the interface with the help of special attributes of HTML tags, and not directly in the JS code. In earlier versions of the library, it was the access to the declarative model, when in HTML code the developer described form using attributes, and after loading the browser Dojo replaced the descriptions with rendered elements. Later, after a cardinal change of architecture and a transition to the 0.9 branch, and then in 1.x, it turned out that the program model is more familiar and, most importantly, faster, especially in complex forms. And debugging seems simpler, and the possibilities are wider.

Widget startup

The final method for creating a widget is the startup () method. This method is especially useful when we need to perform any actions after the widget has been completely initialized and rendered, but before it is displayed on the page. For example, if we need to add any element to the widget or a new tab to the tab container of the widget, then we can easily do this in the startup method.
The startup method will automatically be called by the parser in the case of a widget's declarative declaration, however, if we create the widget programmatically, we need to call this method manually.

Deferred performance of "heavy" functions.

As we all know very well, multi-threading in JavaScript is out of the question. All JavaScript code will be executed in the same thread. Therefore, the implementation of "heavy" (resource-intensive) tasks is better to postpone for the last moment.
To do this, we can use timers in JavaScript, namely the setTimeout and setInterval functions, which allow us to organize deferred code execution after a specified period of time. In this case, the execution of the deferred code is shifted to the execution queue of the JS engine, which makes it possible to complete the execution of more critical tasks.
  1. dojo.addOnLoad ( function () {
  2. setTimeout ( function () {
  3. // deferred code
  4. }, 100);
  5. });
* This source code was highlighted with Source Code Highlighter .

More details about using timers to optimize JavaScript code can be found here .

dojo.query

Use dojo.query to access the DOM. Yes, dojo.query is much faster and has a laconic syntax than regular DOM APIs. For example, this code:
  1. // list every node with the class "progressIndicator":
  2. var list = [];
  3. var nodes = .getElementsByTagName ( "*" );
  4. // iterate over every node in the document .... SLOOOW
  5. for ( var x = 0; x <nodes.length; x ++) {
  6. if (nodes [x] .className == "progressIndicator" ) {
  7. list.push (nodes [x]); }}
  8. console.dir (list);
* This source code was highlighted with Source Code Highlighter .

using dojo.query looks like this:
  1. console.dir (dojo.query ( ".progressIndicator" ));
* This source code was highlighted with Source Code Highlighter .

You can find more diverse examples of using dojo.query using different queries here .

dojo.behavior

Use dojo.behavior to add functionality. dojo.behavior is a very simple and easy mechanism for “adding” code to existing documents, which is based on dojo.query for selecting DOM elements and two simple API commands:
dojo.behavior.add (), which adds a “behavior object” to the document, and dojo.behavior.apply (), which applies the added “behavior”.
With examples of use can be found here .

Event Delegation

"Hanging" the same handlers on several different elements can be optimized using delegation. The point of this optimization of event processing is to “hang” one handler per common parent element and use the event object obtained in the handler arguments to access the event initiator.
  1. < div id = "container" >
  2. < div id = "1" > 1 </ div >
  3. < div id = "2" > 2 </ div >
  4. < div id = "3" > 3 </ div >
  5. < div id = "4" > 4 </ div >
  6. < div id = "5" > 5 </ div >
  7. </ div >
* This source code was highlighted with Source Code Highlighter .

Without delegation:
  1. for ( var i = 1; i <6; i ++) {
  2. var el = dojo.byId ( "" + i);
  3. dojo.connect (el, "onclick" , function () {
  4. alert ( this .id);
  5. }); }
* This source code was highlighted with Source Code Highlighter .

Using delegation:
  1. dojo.connect (dojo.byId ( "container" ), "onclick" , function (evt) {
  2. var el = evt.target;
  3. alert (el.id);
  4. });
* This source code was highlighted with Source Code Highlighter .


On a note

And finally, general code optimization ideas using the Dojo framework:

In addition, the following critical factors should be kept in mind:

Conclusion


Well, perhaps all that I wanted to dwell on in this article. Of course, this article does not claim to be the complete or “best” guide to optimizing JS code and / or Dojo widgets, but I tried to focus on the most significant and frequently used principles. I hope this article will be useful to anyone who uses or plans to start using the Dojo JavaScript framework .

upd : Thanks for the karma - transferred to the Javascript blog.

Source: https://habr.com/ru/post/86078/


All Articles