В августе 2008 года команда Yahoo User Interface выпустила первый предварительный выпуск YUI 3, полностью переписанный YUI с нуля (первый бета-выпуск которого должен быть выпущен на следующей неделе!).
Вы спросите, почему они переписывают уже полезную и зрелую библиотеку? Ну, когда YUI 2 повзрослел, то, как он был построен, также изменилось.
В результате части YUI, которые присутствовали с самого начала, были закодированы совершенно иначе, чем части, которые были добавлены позже. В результате библиотека содержала несоответствия — как во внутренней механике, так и в API. Итак, команда решила, что вернет библиотеку к основам и восстановит ее с нуля. Их план состоял в том, чтобы применить опыт, полученный за последние три года работы над YUI, и создать библиотеку, которая была бы легче, быстрее и проще в использовании. Наконец, в попытке сделать библиотеку максимально гибкой, YUI 3 представляет совершенно новую архитектуру плагинов, которая позволяет добавлять свои собственные функции к узлам и виджетам. Мы увидим один такой плагин в действии чуть позже. Для начала посмотрим, что нового в YUI 3.
До свидания YAHOO
, привет YUI
Первое, что вы заметите, глядя на примеры кода YUI 3, — это новое имя глобального объекта, которое оно использует. Старый глобальный объект YAHOO
был заменен новым глобальным объектом YUI
. Он был переименован по нескольким причинам: по отзывам пользователей, некоторые компании не хотели, чтобы в их коде было имя Yahoo; но что еще более важно, он позволяет более старым версиям YUI сосуществовать с YUI 3 благодаря другому имени переменной.
Как и глобальный объект, который переименовывается, его использование основано на принципиально ином принципе, чем в 2.x. Для начала, это уже не статический объект, а функция, которая при выполнении возвращает свой экземпляр. Теперь каждое выполнение YUI
возвращает автономную среду, в которой версия библиотеки и версия всех ее загруженных компонентов могут работать, не мешая любому другому экземпляру YUI на странице. По расширению это также означает, что несколько версий библиотеки могут сосуществовать на одной странице, создавая различные версии объекта YUI
. Пример ниже иллюстрирует этот принцип:
YUI().use('dd-drop', 'anim', function(Y) { // Y.DD is available // Y.Anim is available }
Здесь выполняется YUI()
, который возвращает экземпляр библиотеки, из которой выполняется метод use
. Требуется минимум два параметра: компоненты библиотеки, затем обратный вызов для запуска, как только все будет загружено. В нашем примере выше, первые два параметра, переданные для use
являются именами компонентов библиотеки, которые должны быть загружены. Последний параметр — это наша функция обратного вызова, которая получает объект (в примере с именем Y
) — это экземпляр библиотеки, содержащей все загруженные компоненты. Таким образом, как и комментарии в приведенном выше примере, компонент перетаскивания можно найти в Y.DD
, а компонент анимации можно найти в Y.Anim
.
Более чистый, более лаконичный стиль кодирования
Одной из основных задач группы было обеспечение согласованной внутренней механики и согласованного API для всех компонентов YUI. Таким образом, YUI 3 теперь имеет новую иерархию классов, которая позволяет именно это. Например, класс Attribute
предоставляет методы get
и set
, поддержку начальной конфигурации и события изменения атрибутов классам, которые его наследуют. Есть также класс Base
который наследуется от Attribute
и предоставляет некоторые готовые объектно-ориентированные функциональные возможности, такие как методы инициализатора и деструктора для всех классов, которые наследуются от него. Наконец, они создали класс Widget
который наследуется от Base
и предоставляет общие функциональные возможности, обычно используемые виджетами, такие как метод рендеринга — общая структура Model-View-Controller для управления рендерингом виджетов — и поддержка общих атрибутов виджетов. Он также обеспечивает регистрацию плагинов и поддержку активации.
Другая проблема, которую преодолевает YUI 3, — это когда ваш скрипт должен загружать тяжелый кусок библиотеки только для одной или двух функций, содержащихся в нем. Например, в YUI 2 вам нужно будет включить всю утилиту подключений (весом 38 КБ, 12 КБ при минимизации) только для выполнения некоторых вызовов XMLHttpRequest
. YUI 3 решает эту проблему путем разделения функциональности на более мелкие подмодули. Таким образом, нет необходимости снимать всю утилиту только для выполнения вызовов XMLHttpRequest
. В YUI 3 вы можете сделать вызов XMLHttpRequest
, только опуская модуль io-base
IO Utility весом всего 19 КБ (уменьшено до 4 КБ). На самом деле вся утилита ввода-вывода весит 29 КБ (уменьшенная до 7 КБ) и обладает гораздо большими функциональными возможностями, чем ее предшественница. Например, теперь можно совершать междоменные вызовы или вызовы io-xdr
подмодулем io-xdr
.
Выбор и цепочка
YUI 2 представил движок селектора, но он сделал это немного поздно в жизни библиотеки. В результате вся библиотека построена на методах извлечения элементов старой школы. Другими словами, вы либо передавали id
элемента, либо сам элемент всякий раз, когда требовалась ссылка, и это было об этом. Однако в YUI 3 механизм выбора встроен прямо в ядро библиотеки. Он пронизывает каждую его часть, так что вы можете передавать строки селектора CSS практически везде, где требуется ссылка на элемент. Помимо конструкторов, это также включает настройку обработчиков событий и работу с утилитами. Вот пример, который делает перетаскиваемый первый элемент с author
класса:
var dd = new Y.DD.Drag({ node: '.author' });
Всякий раз, когда YUI 3 не имеет логического значения для возврата, он пытается сделать метод цепным. Вот пример этого в действии:
Y.get('.author').setStyle('cursor', 'move');
Здесь мы сослались на первый элемент с именем класса author
и установили стиль курсора на нем.
Узлы и Событийные Фасады
YUI 3 представляет новый уровень абстракции для DOM с помощью Node Utility. Вместо того, чтобы возвращать ссылку на элемент DOM, YUI 3 возвращает Node
s и NodeList
s, что значительно упрощает взаимодействие с DOM. Это связано с тем, что Node
включают в себя все функции, необходимые для взаимодействия с ними, а не для перехода к отдельным функциям. Более того, методы, предоставляемые Node
заботятся о нормализации браузера всякий раз, когда это необходимо, поэтому опыт работы с ними является максимально безболезненным. Вот что вам нужно написать в YUI 2, чтобы добавить имя класса к элементу:
YAHOO.util.Dom.addClass("navProducts", "selected");
В YUI 3 это становится:
Y.get("#navProducts").addClass("selected");
Фактически, если узел уже был в распоряжении, скажем, в переменной с именем navProducts
, то вы могли бы просто сделать это:
navProducts.addClass("selected");
YUI 3 упростил взаимодействие с DOM, а также нормализовал управление событиями, используя идею фасада событий. Каждый слушатель события получает фасад события, который заботится о нормализации браузера. Так, например, где в YUI 2 вам понадобился следующий код для «предотвращения дефолта»:
YAHOO.util.Event.on("navProducts", "click", YUI2callback(e) { e = e || event; YAHOO.util.Event.preventDefault(e); });
Теперь все, что вам нужно сделать, это:
navProducts.on("click", YUI3callback(e) { e.preventDefault(); });
Более того, это поведение распространяется и на чисто пользовательские события, поэтому даже они получают фасады событий, которые позволяют им предотвращать дефолт и останавливать распространение.
Далее: давайте применим некоторые из этих новых методов на практике.
Покажи мне деньги!
Я создал простую страницу примера, демонстрирующую, насколько простым и мощным является YUI 3. Чтобы сэкономить место в этой статье, я не буду показывать вам всю разметку и код, но вы можете просмотреть полный исходный код на странице примера.
Первое, что я делаю, это загружаю экземпляр YUI с помощью утилиты анимации, виджета слайдера, плагина MenuNav Node и утилит перетаскивания. YUI отправляет нужные файлы и их зависимости с серверов Yahoo. Затем он возвращает экземпляр YUI с загруженными компонентами в функцию обратного вызова, которая получает его в переменной с именем Y
:
YUI().use('anim', 'slider', 'node-menunav', 'dd-drag', function (Y) { ...
Затем я создаю простую анимацию, чтобы отобразить содержимое страницы. Для этого я создаю новый объект Animation. Я передаю ему ссылку на элемент с идентификатором main
и говорю ему анимировать верхнее значение до 0
от того места, где оно находится в данный момент (сейчас оно имеет значение -1000px
, как указано в разметке страницы примера). Я также указываю, что анимация должна занимать три секунды и что она должна использовать elasticOut
смягченияasticOut. Как только объект создан, это всего лишь простой случай запуска его с помощью метода run
:
/* * Bounce-in Anim */ var anim = new Y.Anim({ node: '#main', to: { top: 0 }, duration: 3, easing: Y.Easing.elasticOut }); anim.run();
Затем я настроил объект Slider
, чтобы позволить пользователям регулировать базовый размер шрифта страницы. CSS-шрифты YUI (включены в пример страницы) устанавливают базовый размер шрифта страницы в 13 пикселей. Это делается путем установки значения font-size
для элемента body
, из которого рассчитываются все остальные размеры шрифта. Это то, что мы собираемся манипулировать, чтобы изменить размеры шрифта всей страницы.
Я взял ссылку на узел для элемента body
, который будет использоваться позже вместе со слайдером. Затем я создаю виджет слайдера. Я установил минимальное значение 13, а максимальное 28, потому что я хочу, чтобы размер шрифта оставался в пределах этих значений. Затем я проверяю, что размер направляющей слайдера составляет 100 пикселей в ширину. Наконец, я установил изображение большого пальца ползунка (которое загружается непосредственно с серверов Yahoo):
/* * Font Size Slider */ var body = Y.get('body'); var slider = new Y.Slider({ min: 13, max: 28, railSize: '100px', thumbImage: 'http://yui.yahooapis.com/3.0.0pr2/build/ slider/assets/skins/sam/thumb-classic-x.png' });
Как только слайдер создан, его просто отрендерить. Я делаю это, вызывая метод render
ползунка с именем класса элемента, в котором я хочу, чтобы он отображался. Виджет слайдера будет отрисовываться в первом элементе DOM, который соответствует имени этого класса:
slider.render('.horiz_slider');
Единственная оставшаяся задача — подключить ползунок так, чтобы он на самом деле регулировал размер шрифта страницы. Это я делаю, подключив его after
события. В YUI 3 есть стандартные функции on
событий after
и after
вы можете подключиться, чтобы сделать обработку таких событий намного проще, чем в предыдущей версии. Теперь, когда valueChange
событие fontStyle
значение fontStyle
элемента нашего body
изменяется:
slider.after('valueChange', function (e) { body.setStyle('fontSize', e.newVal + 'px'); });
Я также настроил навигационное меню. Когда содержимое страницы будет готово, я подключаю плагин Node MenuNav к узлу nav
. Затем он автоматически настраивает навигационное меню на основе найденной разметки — так просто! Вот код:
/* * MenuNav */ Y.on('contentready', function () { this.plug( Y.plugin.NodeMenuNav, {mouseOutHideDelay: 1}); }, '#nav');
Наконец, я делаю вашу фотографию действительно перетаскиваемой, просто создавая экземпляр нового объекта перетаскивания и передавая ему ссылку на имя класса моей картинки. Как только объект создан, изображение можно перетаскивать. В качестве дополнительного прикосновения я меняю курсор мыши, когда он наводит курсор на изображение, чтобы было видно, что изображение можно перетаскивать:
/* * Drag and Drop */ var dd = new Y.DD.Drag({ node: '.author' }); Y.get('.author').setStyle('cursor', 'move'); });
Резюме
Итак, как видите, YUI 3 — это совершенно другое животное, чем его предшественник. Наряду с новым синтаксисом вы получаете более быструю, легкую, простую и более гибкую библиотеку, готовую принять самые амбициозные веб-проекты.
Видя, что это был учебник, мы чуть-чуть поцарапали поверхность того, что возможно с YUI 3. Для получения дополнительной информации посетите страницу YUI 3.x Preview Release 2 , презентацию Satyen Desai по YUI 3 и форум YUI 3 .