Доброго времени суток, хабрасообщество.
Хочу поделиться с вами некоторой полезной, на мой взгляд, информацией, которой будет интересна тем, кто разрабатывает или планирует начать разрабатывать свои Dojo виджеты. Хочу сразу предупредить, что в данной статье я не буду рассказывать как поэтапно создать свой виджет Dojo (однако, если сообществу будет интересна и эта тема, я надеюсь изложить ее в отдельной статье). Вместо этого я хочу остановиться на основных моментах и принципах, которые следует знать и учитывать каждому, кто занимается разработкой Dojo виджетов или имеет какое-либо отношение к этой теме.
Думаю не будет лишним сказать пару слов о концепции виджетов.
Цель виджетов Dojo — инкапсуляция визуальных Web-компонентов с целью многократного последующего использования. Виджет Dojo обрабатывается на стороне Web-браузера.
Структура виджетов Dojo не зависит от структуры объектов DOM. Каждый виджет Dojo имеет уникальный widgetId и может не содержать ни одного, или же содержать один или более элементов DOM, а также дочерние виджеты Dojo.
Виджет состоит из нескольких файлов. Необходимым является файл JavaScript-кода, в то время как другие необязательны:
Dojo позволяет нам создавать виджеты двумя способами: декларативно и программно.
Программно мы можем инстанциировать виджет посредством кода JavaScript:
Декларативно виджеты создаются непосредственно через разметку:
Виджеты, объявленные декларативно, будут обнаружены и инстанциированы парсером dojo сразу после body.load события и перед вызовом функций из dojo.addOnLoad. Поэтому, чтобы не блокировать поток исполнения, лучше всего откладывать исполнение ресурсоемких задач на addOnLoad везде где это возможно.
Разработчики Dojo явно тяготеют к описанию интерфейса при помощи специальных атрибутов HTML-тегов, а не напрямую в JS-коде. В ранних версиях библиотеки была доступа именно декларативная модель, когда в HTML-коде разработчик при помощи атрибутов описывал форму, а после загрузки в браузере движок Dojo заменял описания на отрендеренные элементы. Позже, после кардинальной смены архитектуры и перехода на ветку 0.9, а затем и в 1.х оказалось, что программная модель привычнее и, что важнее всего, быстрее, особенно в условиях сложных форм. Да и отладка кажется более простой, а возможности шире.
Заключительным методом создания виджета является метод startup(). Этот метод особенно полезен в тех случаях, когда нам необходимо выполнить какие-либо действия после того, как виджет полностью был инициализирован и отрендерен, но до того, как он будет отображен на странице. Например, если нам необходимо добавить какой-либо элемент к виджету либо новый tab к tab container-у виджета, то мы можем легко это сделать в методе startup.
Метод startup автоматически будет вызван парсером в случе декларативного объявления виджета, однако если мы создаем виджет програмным способом, то нам необходимо вызывать этот метод вручную.
Как мы все прекрасно знаем, о многопоточности в JavaScript не может быть и речи. Весь JavaScript код будет выполняться в одном и том же потоке. Поэтому, выполнение «тяжелых» (ресурсоемких) задач лучше откладывать на последний момент.
Для этого мы можем использовать таймеры в JavaScript, а именно функции setTimeout и setInterval, которые позволяют организовать отложенное выполнение кода через указанный промежуток времени. При этом выполнение отложенного кода смещается в очереди исполнения JS движка, что дает возможность закончить выполнение более критических задач.
Более подробно об использовании таймеров для оптимизации JavaScript кода можно прочесть здесь.
Используйте dojo.query для доступа к DOM. Да, dojo.query гораздо быстрее и имеет более лаконичный синтаксис, чем обычные DOM APIs. Например, этот код:
с использованием dojo.query выглядит следующим образом:
Больше разнообразных примеров использования dojo.query с применением различных запросов вы можете найти тут.
Используйте dojo.behavior для добавления функционала. dojo.behavior представляет собой очень простой и легкий механизм «добавления» кода в существующие документы, который основан на dojo.query для отбора DOM-элементов и двух простых команд API:
dojo.behavior.add(), которая добавляет «поведенческий объект» (behavior object) к документу, и dojo.behavior.apply(), который применяет добавленное «поведение».
С примерами использования можно ознакомиться тут.
«Навешивание» одинаковых обработчиков на несколько разных элементов может быть оптимизировано при помощи делегирования. Смысл данной оптимизации обработки событий состоит в том, чтобы «повесить» один обработчик на один общий родительский элемент и использовать получаемый в аргументах обработчика event object для доступа к инициатору события.
Без делегирования:
С использованием делегирования:
И напоследок, общие идеи оптимизации кода с использованием Dojo фреймворка:
Кроме того, следует помнить и учитывать следующие критические факторы:
Ну вот пожалуй и все, на чем я хотел остановиться в данной статье. Конечно данная статья не претендует на полный или «самый лучший» справочник по оптимизации JS кода и/или Dojo виджетов, однако я постарался остановиться на наиболее значимых и часто используемых принципах. Надеюсь эта статья будет полезна всем, кто пользуется или планирует начать пользоваться JavaScript фреймворком Dojo.
upd: Спасибо за карму — перенес в блог Javascript.
Хочу поделиться с вами некоторой полезной, на мой взгляд, информацией, которой будет интересна тем, кто разрабатывает или планирует начать разрабатывать свои Dojo виджеты. Хочу сразу предупредить, что в данной статье я не буду рассказывать как поэтапно создать свой виджет Dojo (однако, если сообществу будет интересна и эта тема, я надеюсь изложить ее в отдельной статье). Вместо этого я хочу остановиться на основных моментах и принципах, которые следует знать и учитывать каждому, кто занимается разработкой Dojo виджетов или имеет какое-либо отношение к этой теме.
Dojo виджеты
Думаю не будет лишним сказать пару слов о концепции виджетов.
Цель виджетов Dojo — инкапсуляция визуальных Web-компонентов с целью многократного последующего использования. Виджет Dojo обрабатывается на стороне Web-браузера.
Структура виджетов Dojo не зависит от структуры объектов DOM. Каждый виджет Dojo имеет уникальный widgetId и может не содержать ни одного, или же содержать один или более элементов DOM, а также дочерние виджеты Dojo.
Виджет состоит из нескольких файлов. Необходимым является файл JavaScript-кода, в то время как другие необязательны:
- Файл JavaScript-кода (*.js) содержит логику виджета на JavaScript. Он управляет визуальными элементами с помощью API объектов DOM JavaScript. (В Dojo имеется множество полезных библиотек для упрощения стандартных функций.)
- HTML-шаблон (*.html) обеспечивает базовое представление виджета в HTML. Если шаблон очень прост, можно представить его виде строки в файле кода.
- Файл стиля CSS (*.css) содержит визуальные стили, используемые HTML-шаблоном и/или кодом JavaScript.
- Файлы изображений (*.gif, *.jpg, etc.) содержат изображения, используемые виджетом.
Практический опыт по созданию виджетов.
Программная и декларативная модели создания виджетов Dojo
Dojo позволяет нам создавать виджеты двумя способами: декларативно и программно.
Программно мы можем инстанциировать виджет посредством кода JavaScript:
- var myWidget = new WidgetClass({
- //properties
- },”targetNode”);
* This source code was highlighted with Source Code Highlighter.
Декларативно виджеты создаются непосредственно через разметку:
- <div dojoType=“WidgetClass”></div>
* This source code was highlighted with Source Code Highlighter.
Виджеты, объявленные декларативно, будут обнаружены и инстанциированы парсером dojo сразу после body.load события и перед вызовом функций из dojo.addOnLoad. Поэтому, чтобы не блокировать поток исполнения, лучше всего откладывать исполнение ресурсоемких задач на addOnLoad везде где это возможно.
- <div dojoType=“myWidgetClass” postCreate=“slowFunction”></div>
- //Медленный вариант:
- slowFunction(){doSlowStuff();}
- //Оптимизированный вариант:
- slowFunction(){dojo.addOnLoad(doSlowStuff());}
* This source code was highlighted with Source Code Highlighter.
Разработчики Dojo явно тяготеют к описанию интерфейса при помощи специальных атрибутов HTML-тегов, а не напрямую в JS-коде. В ранних версиях библиотеки была доступа именно декларативная модель, когда в HTML-коде разработчик при помощи атрибутов описывал форму, а после загрузки в браузере движок Dojo заменял описания на отрендеренные элементы. Позже, после кардинальной смены архитектуры и перехода на ветку 0.9, а затем и в 1.х оказалось, что программная модель привычнее и, что важнее всего, быстрее, особенно в условиях сложных форм. Да и отладка кажется более простой, а возможности шире.
Widget Startup
Заключительным методом создания виджета является метод startup(). Этот метод особенно полезен в тех случаях, когда нам необходимо выполнить какие-либо действия после того, как виджет полностью был инициализирован и отрендерен, но до того, как он будет отображен на странице. Например, если нам необходимо добавить какой-либо элемент к виджету либо новый tab к tab container-у виджета, то мы можем легко это сделать в методе startup.
Метод startup автоматически будет вызван парсером в случе декларативного объявления виджета, однако если мы создаем виджет програмным способом, то нам необходимо вызывать этот метод вручную.
Отложенное выполнение «тяжелых» функций.
Как мы все прекрасно знаем, о многопоточности в JavaScript не может быть и речи. Весь JavaScript код будет выполняться в одном и том же потоке. Поэтому, выполнение «тяжелых» (ресурсоемких) задач лучше откладывать на последний момент.
Для этого мы можем использовать таймеры в JavaScript, а именно функции setTimeout и setInterval, которые позволяют организовать отложенное выполнение кода через указанный промежуток времени. При этом выполнение отложенного кода смещается в очереди исполнения JS движка, что дает возможность закончить выполнение более критических задач.
- dojo.addOnLoad(function(){
- setTimeout(function(){
- //отложенный код
- }, 100);
- });
* This source code was highlighted with Source Code Highlighter.
Более подробно об использовании таймеров для оптимизации JavaScript кода можно прочесть здесь.
dojo.query
Используйте dojo.query для доступа к DOM. Да, dojo.query гораздо быстрее и имеет более лаконичный синтаксис, чем обычные DOM APIs. Например, этот код:
- // list every node with the class "progressIndicator":
- var list = [];
- var nodes = .getElementsByTagName("*");
- // iterate over every node in the document....SLOOOW
- for(var x = 0; x < nodes.length; x++){
- if(nodes[x].className == "progressIndicator"){
- list.push(nodes[x]); } }
- console.dir(list);
* This source code was highlighted with Source Code Highlighter.
с использованием dojo.query выглядит следующим образом:
- console.dir( dojo.query(".progressIndicator") );
* This source code was highlighted with Source Code Highlighter.
Больше разнообразных примеров использования dojo.query с применением различных запросов вы можете найти тут.
dojo.behavior
Используйте dojo.behavior для добавления функционала. dojo.behavior представляет собой очень простой и легкий механизм «добавления» кода в существующие документы, который основан на dojo.query для отбора DOM-элементов и двух простых команд API:
dojo.behavior.add(), которая добавляет «поведенческий объект» (behavior object) к документу, и dojo.behavior.apply(), который применяет добавленное «поведение».
С примерами использования можно ознакомиться тут.
Делегирование событий
«Навешивание» одинаковых обработчиков на несколько разных элементов может быть оптимизировано при помощи делегирования. Смысл данной оптимизации обработки событий состоит в том, чтобы «повесить» один обработчик на один общий родительский элемент и использовать получаемый в аргументах обработчика event object для доступа к инициатору события.
- <div id="container">
- <div id="1">1</div>
- <div id="2">2</div>
- <div id="3">3</div>
- <div id="4">4</div>
- <div id="5">5</div>
- </div>
* This source code was highlighted with Source Code Highlighter.
Без делегирования:
- for (var i = 1; i < 6; i++) {
- var el = dojo.byId("" + i);
- dojo.connect(el, "onclick", function() {
- alert(this.id);
- }); }
* This source code was highlighted with Source Code Highlighter.
С использованием делегирования:
- dojo.connect(dojo.byId("container"), "onclick", function(evt) {
- var el = evt.target;
- alert(el.id);
- });
* This source code was highlighted with Source Code Highlighter.
На заметку
И напоследок, общие идеи оптимизации кода с использованием Dojo фреймворка:
- dojo.parse работает быстрее, чем непосредственный обход DOM;
- добавление элементов к DOM пагубно влияет на производительность;
- каждый виджет – это дополнительная нагрузка, поэтому объединяйте их, где это возможно;
- организовывайте отложенное исполнение везде где это возможно;
- базовые функции Dojo оптимизированы для производительности, однако виджеты могут быть медленными и ресурсоемкими, если не уделять нужного внимания всем деталям при реализации;
Кроме того, следует помнить и учитывать следующие критические факторы:
- Скрипты в body замедляют парсинг body;
- Подгрузка ресурсов блокирует body load event;
- Обработка массивных конструкций виджетов, подлежащих парсингу, блокирует addOnLoad обработчики;
- Массивные (медленные) addOnLoad обработчики блокируют последовательное выполнение остальных обработчиков.
Заключение
Ну вот пожалуй и все, на чем я хотел остановиться в данной статье. Конечно данная статья не претендует на полный или «самый лучший» справочник по оптимизации JS кода и/или Dojo виджетов, однако я постарался остановиться на наиболее значимых и часто используемых принципах. Надеюсь эта статья будет полезна всем, кто пользуется или планирует начать пользоваться JavaScript фреймворком Dojo.
upd: Спасибо за карму — перенес в блог Javascript.