Готовим свой первый веб-компонент

Веб-компоненты (здесь и далее — в целях удобства восприятия — «WC») изобрели умные люди, которым надоело готовить спагетти из шаблонов. WC — это [почти] полностью изолированное от среды выполнения DOM-дерево. Я внимательно прочитал правила сайта, поэтому пересказывать википедию не стану. Если вы не знаете, что такое WC, почитать можно здесь.Tl; dr: демо-страничку компонента, который выводит слайдер с текстом нескольких заметок и кнопками «туда»/«сюда» можно посмотреть прямо сейчас.

WC уже используют многие популярные сайты. Если установить плагин WC, можно посмотреть другими глазами на, например, github:

851d7f557d1d4a45b71a01f7f85c50be.png

выделенное красненьким пунктиром — на картинке выше — WC.

Пока производители браузеров жуют бумагу (на данный момент поддерживают технологию Chrome/Opera и, с оговорками, FF), неравнодушные создают костыли. Первым был, наверное, x-tags от Mozilla (совсем недавно они выкатили библиотеку компонентов Brick, на которую пока смотреть без слез невозможно). Самым удачным костылем был и остается Polymer.

Эти библиотеки эмулируют WC, предоставляя возможность разработчикам уже сегодня писать код, который когда-нибудь в светлом будущем будет выполняться во всех браузерах нативно.

Например, в этой заметке мы создадим WC, который будет показывать пользователю несколько статей (слайдер для текстового контента). Без перезагрузки страницы, с предупреждающей загрузкой соседей и прочим блэкджеком. Шаблон страницы при этом будет выглядеть вот так (ну, там еще не относящиеся к делу меты будут, IE хелперы и всякая дребедень, наверное; для всех современных браузеров этого шаблона, впрочем, достаточно):

Постановка задачи Пусть у нас есть сервер, который умеет отдавать json в таком виде: { «href»: «demo.html?0», /* html-ссылка для корректной обработки browser history*/ «caption»: «Title 0», /* заголовок окна */ «prev»: null, /* ссылка на json с предыдущей заметкой */ «next»: «data/data1.json», /* ссылка на json со следующей заметкой */ «text»:»

Header 0

Lorem ipsum …

» /* контент */ } И мы хотим показывать этот контент и навигацию по «предыдущая»/«следующая», поддерживая при этом историю браузера. Для этих целей идеально подойдет WC. Итак, приступим.

Средства достижения цели WC (как и все нынче) принято готовить из рыбы (шаблона, скелета, котельного листа, бойлерплаты). Для генерации рыбы будем использовать Йомена. Документация на Yeoman существует в сети, да она особо и не требуется: все сделано для домохозяек, как КОБОЛ.8aa953253f4584597327fe40a4bae8e6.jpg

Устанавливаем все необходимое (для альтернативных ОС инструкции можно найти у поставщиков), а также генератор шаблонов для полимера:

npm install -g yo bower grunt npm install -g generator-polymer Готовые компоненты для своего проекта можно искать на component.kitchen и customelements.io, но мы будем готовить по своему рецепту.

Создаем папку, пусть будет polymer, в ней создаем подпапку с именем нашего компонента (их принято называть в стиле prefix-name), переходим туда и запускаем генератор:

mkdir -p polymer/mudasobwa-slider && cd $_ && yo polymer: seed Отвечаем на несколько несложных вопросов — и мы почти у цели. Давайте посмотрим, что нам нагенерили.

bower.json index.html demo.html mudasobwa-slider.html mudasobwa-slider.css Отлично. Нам потребуются стандартные компоненты для ajax-вызовов, ну и font-awesome для красивых иконок:

bower install --save Polymer/core-ajax bower install --save 'polymer-fontawesome=rtbenfield/polymer-fontawesome#master' Эта команда скачает пакеты, с зависимостями, и обновит наш манифест. Выполним bower install и полюбуемся на нашу рыбу (любой простейший сервер запускаем в заглавном каталоге polymer (NB! на уровень выше нашего компонента):

python -m SimpleHTTPServer Можно сходить браузером по адресу http://localhost:8000 и полюбоваться на дело рук, пока, правда, не наших. Пора немного и покодировать.

Работа с содержимым Тут все, как мы привыкли: такой же javascript, такой же html. Есть всего несколько вещей, которые стоит знать, чтобы кофмортно себя чувствовать: К свойствам есть доступ через переменную this (из скрипта) и через псевдокод {{ ИМЯ_ПЕРМЕННОЙ }} в html; К дочерним компонентам есть доступ через переменную this.$ (sic!); Публичные свойства — декларируются в свойстве attributes основного тега компонента; У shadow-dom есть дополнительные псевдоэлементы, типа : host Что это все означает? Давайте разберемся по коду. Наибольший интерес представляет собой компонент, который занимается обменом данными с сервером, своего рода controller из концепции MVC. Модель я описал (это json, который мы волшебным образом получаем с сервера, тут WC не помогут), на view остановимся чуть позже.

Controller Наш WC зовут «mudasobwa-content-loader», у него есть видимые свойства (атрибуты) url href article caption prefetch next prev stateable (в polymer.js иногда появляются трудновылавливаемые баги, связанные со «слишком стандартными» именами атрибутов, совсем недавно я чуть не поседел, пока понял, отчего FF молча отказывался иметь дело с компонентом у которого был атрибут «title»; это чинят, но имена атрибутам все равно лучше давать позаковыристей), он невидим, и использует WC «core-ajax» для (сюрприз) ajax-вызовов. Также он содержит два таких же, как он сам компонента для прелоадинга соседей (с выключенной опцией «prefetch», иначе каждый сосед потянет за собой своих соседей и так далее). Параметр «url» будет обновляться автоматически в пределах компонента, например, если мы вызовем this.url = http://example.com, core-ajax об этом узнает (и если бы у него была включена опция «auto», он бы сам вызвал автообновление, а получив новый ответ от сервера — вызвал бы метод нашего компонента contentLoaded). У нас автообновление отключено, чтобы не слать лишние запросы.

Скрипт тоже не особо заковырист. Посмотрим, например, на handler contentLoader:

В секции body:

Получившийся WC сам сходит на сервер за соседними заметками, нарисует (или не нарисует, если текущий элемент — крайний) стрелочки управления «вперед»/«назад», его можно было бы еще обучить предзагружать картинки соседних заметок, но это совсем уже раздует и так немаленькую заметку.

А что с индексированием? — обязательно спросит тут внимательный читатель. Ну, гугл, вроде, умеет. Яндекс, кажется, нет. Найти внятные заявления «да, поддерживаем», или «нет, не поддерживаем» мне не удалось. Поэтому технология пока идеально подходит только для маленьких сниппетов, индексирование которых не важно (см. КДПВ с гитхаба). Но я искренне верю в то, что за WC — недалекое будущее. Уж больно удобно.

Я надеюсь, что основные аспекты создания своего WC с нуля я более-менее осветил. Если есть вопросы — задавайте в комментариях. Если я что-то важное упустил — буду признателен за советы.

The summing up  — демо— весь код примера на github— на хабре: 1, 2

© Habrahabr.ru