Веб-компоненты в реализации Polymer от Google


Веб-компоненты — это новая эра веб-разработки и почувствовать ее мощь можно уже сегодня при помощи Polymer от Google. Вы можете создавать свои собственные «элементы» (тэги), содержащие шаблон и инкапсулированные стили и логику (js), а так же воспользоваться богатой коллекцией уже готовых элементов.

Что такое Polymer?


Polymer это библиотека (сами они называют это, набором полифилов и синтаксического сахара) для создания и использования веб-компонент. А веб-компоненты это некий набор стандартов W3C, который в будущем будет поддерживаться уже поддерживается некоторыми браузерами. Если совсем по-простому, то веб-компонента это некий выделенный в отдельный блок кусок html кода с шаблонированием, стилями и логикой. Это позволяет повысить структурированность вашего html кода, повысить читаемость и повторное использование. Один раз написал (или выбрал из стандартных) и используй везде.

Если вы думаете, что html5 изменил веб, то подождите и увидите, что сделают Веб-компоненты. © чей-то.

Проникнуться идеей веб-компонент можно на webcomponents.org. Поковыряться в чужих компонентах можно на component.kitchen.
Ну и еще существует большая вероятность, что Polymer-ное виденье будущего станет реальностью, и вы в будущем просто отключите полифилы Polymer-а (platform.js) и все продолжит работать нативно (UPD: внес уточнение. Спасибо nazarpc). Как мы понимаем, такие компании, как Google и Mozilla (они разрабатывают похожий x-tag) могут менять будущее веба.

Инфраструктура


Для того, чтобы теорию подкрепить практикой, нам нужна инфраструктура. Самый простой способ создать ее – это yeoman и генератор Polymer для него (и конечно нужен Bower). Ниже необходимые команды (уже установленное у вас — пропускайте).

npm install -g bower
npm install -g yo
npm install -g generator-polymer
mkdir my-project
cd my-project
yo polymer

В результате получаем начальный скелет приложения с парой собственных элементов, а также папку со всей коллекцией готовых элементов. Для того, чтобы посмотреть, как это выглядит в работе, нужно запустить сервер.

grunt serve

После запуска откроется браузер и Вы увидите такую картинку:



Итак, когда инфраструктура налажена, приступим к изучению:

Использование готовых компонент и элементов.


Polymer содержит две основные коллекции элементов:

  • Core-elements – это набор элементов, включающий визуальные элементы (панельки, кнопки, инпуты и пр) и не визуальные элементы (ajax, localstorage и т.д ).
  • Paper-elements – это набор элементов, реализующий новый material design, последнее время широко используемый Google.

Для использования элементов в index.html должен быть подключен (у нас уже все подключено) platform.js:

<script src="bower_components/platform/platform.js"></script>

Также нужно импортировать при помощи тега <link> нужные нам элементы до их использования:

<link rel="import" href="bower_components/[папка]/[элемент].html">

Потом просто вставляете нужные теги в ваш код и все:

<core-scaffold>
  <core-header-panel mode="seamed" navigation flex>
    <core-toolbar></core-toolbar>
    <core-menu valueattr="label">
      <core-item icon="settings" label="Item1"></core-item>
      <core-item icon="settings" label="Item2"></core-item>
    </core-menu>
  </core-header-panel>
  <google-map></google-map>
</core-scaffold>

Для API Google есть готовые компоненты, например <google-map></google-map>. Это позволяет легко встраивать сервисы Google в наше приложение. Смотрите список компонент на googlewebcomponents.github.io.
По быстрому накидать готовых компонент на страницу, подправить стили и js код, посмотреть, как это все выглядит можно при помощи Design tool. С помощью нее можно потом сохранить полученный код как Github Gist.
Вот небольшое видео о работе в этом «редакторе».

Создание элементов


Это, пожалуй, самая главная фишка веб-компонент и Polymer-а (по крайней мере для меня). Это похоже на директиву Angular, только с нормальным html со стилями и логикой. При чем все это изолированно и работает в своем скопе и ни кто из вне ничего не поломает.
Выглядит это так: (я создам элемент <habrauser-card>. Начну с пустого habrauser-card.html в папке app/elements):

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="habrauser-card" attributes="habrauser usercolor">
  <template>

    <style>
    :host {
      display: block;
      padding: 10px;
      color: {{usercolor}};
    }
    polyfill-next-selector { content: ':host h3'; }
    :host ::content h3 {
      margin: 0;
      text-decoration: underline;
    }
    </style>

    <content select="h3"></content>
    <li>I am habrauser <b>{{habrauser}}</b></li>
    <li><content></content></li>

  </template>
  <script>

    Polymer('habrauser-card', {
      habrauser: 'DefaultValue',
      usercolor: 'green'
    });

  </script>
</polymer-element>

Давайте разберем:
Сначала подключаем polymer.html или любую другую компоненту, внутри которой уже есть линк на polymer.html.
Затем в тэге <polymer-element> определяем наш элемент <habrauser-card> (Важно! Имя должно быть обязательно со знаком '–'). В свойстве attributes перечисляем внешние (которые будем использовать при вызове) свойства. Я бы назвал это интерфейсом веб-компоненты. Их еще можно задать через js и свойство publish:, но способ задания через аргумент предпочтительнее.
Дальше идет шаблон на языке html (то, что заключено в теги <template>).
Стили можно писать прямо здесь в тэг <style>, а можно подгружать внешний файл (все как в обычном html). Причем Polymer задержит «регистрацию» элемента до полной загрузки таблицы стилей. :host — это селектор нашего <habrauser-card> элемента, т.е. корневой.
В тег <content> подставиться то, что заключено в наш тег <habrauser-card> при вызове. Содержимое тега <habrauser-card> можно даже разобрать по 'внутренним' тегам, и вывести в нужных местах. Для этого используется аргумент select у тэга <content>.
Ну и в конце тег <script>, в котором естественно js, его тоже можно подгрузить в виде файла. Polymer([tag-name,] [prototype]) — это удобная обертка для привязки свойств и методов к элементу.
И конечно дата-байдинг. Просто вставьте «двойные усы» {{param}} в текст, в атрибуты, в стили, везде и все работает. Если переменная изменится, то поменяется везде и сразу. Причем если это внешняя переменная (интерфейс), то измененное значение можно передать «наверх».
Вот и все компонента описана и теперь можно ее использовать в index.html:

<!-- добавляем линк на наш элемент -->
<link rel="import" href="elements/habrauser-card.html">
...
<div class="hero-unit">
...
  <!-- вызываем наш элемент несколько раз -->
  <habrauser-card habrauser='Petya' usercolor='red'>This text from index.html</habrauser-card>
  <habrauser-card habrauser='Ivan'><h3>Hello!</h3> The end text!</habrauser-card>
  <habrauser-card usercolor='blue'><input placeholder="type here"></habrauser-card>
</div>

После сохранения в браузере Вы увидите такую картинку:



Давайте попробуем немного расширить функционал нашей компоненты: по клику на наше имя вызовем функцию:

...
    <li>I am habrauser <b on-click="{{resetColor}}">{{habrauser}}</b></li>
...
    Polymer('habrauser-card', {
      habrauser: 'DefaultValue',
      usercolor: 'green',
      resetColor: function() {
        this.usercolor = 'green';
      }
...

и в index.html тоже немного подправим, обернув в тэг <template> наши вызовы (для работы дата-биндинга в нашем index.html).

<template is="auto-binding">
  <habrauser-card habrauser="Petya" usercolor="red">This text from index.html</habrauser-card>
  <habrauser-card habrauser="Ivan"><h3>Hello!</h3> The end text!</habrauser-card>
  <habrauser-card usercolor="{{newcolor}}"><input placeholder="type here" value="{{newcolor}}"></habrauser-card>
</template>


Результат будет такой:



Ну и последний пример — это массив и repeat по нему. Замените в index.html:

<div class="hero-unit">
  <yo-greeting></yo-greeting>
  <p>You now have</p>
  <yo-list></yo-list>

  <template id="my-tpl" is="auto-binding" repeat="{{habrausers}}">
    <habrauser-card habrauser="{{name}}" usercolor="{{color}}">{{text}}</habrauser-card>
  </template>
</div>

<script>
  document.querySelector('#my-tpl').habrausers = [
    {name: 'Vasya', color: 'red',    text: 'It is a good day!'},
    {name: 'Petya', color: 'green',  text: 'Are you clever?'},
    {name: 'Masha', color: 'violet', text: 'I am beautifull!'},
    {name: 'Ira',   color: 'orange', text: 'It is a future!'}
  ];
</script>

Результат будет такой



И напоследок, крайне рекомендую посмотреть видео с Google I/O 2014 — Раз и Два

Ну и самая главная ссылка этого поста, куда в случае заинтересованности придется не раз обращаться.
Поделиться публикацией
Похожие публикации
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 27
    +13
    Я вот не понимаю восторгов в стиле «WebComponents изменят весь веб». С чего бы? У нас и сейчас есть тонны готовых компонент россыпью и пачками, и то что они живут не в shadow dom — не сильно кому и мешает.

    Мешает совсем другое — наоборот их слабая связанность. Чтобы из компонент можно было собирать приложение, они хотя бы выглядеть должны одинаково. Не говоря уже о том, чтобы иметь одинаковый UX, уметь гибко вкладываться друг в друга собираясь в более крупные компоненты, иметь общую модель databinding-а, и т.п.
      +2
      Именно. Модель component.io, где компоненты — просто npm-модули, выглядит гораздо привлекательнее. А уже как эти модули обернуты — будь то в веб-компонент, standalone, jquery-плагин, browserify или другой сборщик — это отдельный вопрос, — вопрос потребителя.
      Поэтому разработка компонента сразу в целевую систему — странное занятие. Это все приводит к тому, что в мире js есть море дубликатов одного и того же.
        +1
        Всё, что напрягает в «готовых компонентах россыпью и пачками» — это необходимость каждый раз для контролов копировать определённую вермешель разметки из документации, затем не забывая инициализировать из JS. Я бы не отказался от WebComponents в этом контексте. Особенно это касается замысловатых input-контролов, которые оборачиваются как-нибудь вокруг стандартных.
          0
          Давайте я вам на живом примере объясню, почему восторг такой.

          Как мы обычно делаем в случае с какой-нибудь аякс-страницей:

          <script src="jquery.js"/>
          <script src="jquery.slider.js"/>
          <div class="slider"/>
          <script>
          $('.slider').slider();
          </script>
          

          Что вы делаете в веб-компонентах
          <link rel="import" href="slider.html"/>
          <my-slider/>
          


          Все. Вам не нужно отлавливать внутренние переходы на страницы для redraw. Не нужно как-то навешиваться. Это самостоятельный модуль, и он не относится к основной логике страницы.
            0
            И кода гораздо меньше.
              +5
              Если пишешь на jQuery в стиле «вермишелька» — то всё что угодно будет казаться дзеном.
                0
                у меня по сравнению с angular-ом кода меньше выходит. (jquery нету)
              0
              paper-elements например вполне «одинаково выглядящая коллекция».
              Посмотрите видео «Два» в конце.

              WebComponents не готовые изменят веб, а подход к разработке.
              +1
              Я так и не понял, гугл собирается ангуляр на эту технологию переводить или нет? Я так понимаю они еще перевод на дарт не закончили, а тут и polymer подоспел.
              И возможно ли использовать какую-то связку этих компонент, как совсем базовый ангуляр? Есть ли сборки какие-то?
                0
                Собирается, только постепенно, пока это ещё альфа, которая с трудом и тормозами работает только в evergreen браузерах. Никто тестами производительности пока не занимался (а там есть чем заняться) и т.п. Много вопросов пока.
                Тем не менее, они отказались в Dart от Web UI и портируют Polymer на Dart www.dartlang.org/polymer/

                Если Angular с блекджеком Dart и полимерами взлетит через год другой — всем будет интересно.
                  0
                  да, angularjs 2.0 будет поддерживать веб-компоненты, доки по архитектуре angularjs 2.0 в открытом доступе, там все подробно описано — drive.google.com/?pli=1&authuser=0#folders/0B7Ovm8bUYiUDR29iSkEyMk5pVUk
                  –5
                  что-то картинка к топику на логотип РЖД похожа…
                  image
                    +2
                    Как-то мой мозг не успевает за «инновациями» гугла в вебе…
                      0
                      Хм. А вроде сто лет назад уже была кухня с xml + стили + трансформация = html… Это не те же яйца, только в профиль?
                        0
                        То же чего-то не пойму. Создали в xsl-стиле именованный template в который параметрами принимаем любые значения для любой визуализации, а далее ссылаемся на него в любом месте страницы. Этот template ровно так же может сидеть в отдельных подгружаемых xsl-файлах.

                        Гуру, подскажите где разница-то???! 14 лет назад работало!
                        +1
                        В очередной раз изобрели COM?
                          0
                          Выше уже сказали, что это работает медленно. Но судя по тому как оно работает, оно в принципе не может быстро работать, так как перпендикулярно логике рендринга в браузера. Скорее всего такой подход не сильно будет ухудшать ситуацию с single page приложениями, но вот с более классическими сайтами всё не понятно.
                          На сколько я могу смотреть, абсолютно всё на SinglePage не перевести (если у вас не NodeJS то много гемора с SEO). А если тягать CSS/JS в произвольных местах при каждой загрузке страницы явно перебор.
                          Сейчас мы стараемся уменьшить количество загрузок CSS и загрузить его раньше всех, а JS поставить прям перед (ну не весь конечно). Или shadow dom из веб компонентов позволяет не ждать его загрузки, для отображения самой страницы?
                          Короче это всё в моём понимании ломает pipe line рендринга страницы.
                          Если я не прав и мои страхи беспочвенны то пожалуйста напишите, в целом идея изоляции компонентов она интересная.
                            +2
                            Совершенно не перебор. В Polymer есть такое понятие как вулканизация, когда скрипты и стили встраиваются в тот же файл, что и html, потом несколько html можно объединить, зажать gzip, и работает это очень быстро. Я у себя в движке сделал поддержку Web Components, так что они автоматически разруливаются по зависимостям и объединяются. Вулканизацию пока не применял, хотя, возможно, и стоит. Так вот нативно в Chromium работает шустро, в Firefox с полифилами медленнее, но вполне нормально, а с HTTP 2.0 вообще будет красота, никакой вулканизации не нужно будет.

                            Совершенно нормально работает с не-SinglePage страницами, отлично индексируется поисковиками, так как HTML кода на выходе меньше, по сути только контент, и для изменения представления достаточно изменить веб-компонент, а не исходный HTML, это то о чём я уже давно говорил на счёт шаблонизаторов.

                            Рендеринг не ломает, просто попробуйте поработать — увидите. Как пример могу показать приложение для Firefox OS — там исключительно веб-компоненты, и работает нормально, ещё один проект с закрытым кодом, потому показать не могу, но, скорее всего, некоторые компоненты для форм (выпадающие списки, инпуты, чекбоксы кастомные и прочее) будут позже выложены в Open Source.

                            А ещё веб-компоненты это не обязательно Polymer, как считает автор статьи:

                            Ну и еще существует большая вероятность, что Polymer-ное виденье будущего станет реальностью, и вы в будущем просто отключите Polymer и все продолжит работать нативно.

                            Polymer — это отдель ностоящая штука, как jQuery, скорее всего в браузеры встроена не будет. А вот полифилы Polymer Platform — да, можно будет когда-то отключить.
                              0
                              Я не считаю что веб-компоненты это Polymer. Возможно не правильно выразился. Я имел ввиду именно полифилы.

                              По скорости поддерживаю, по крайней мере то что я протестировал — работает быстрее angular-a, даже в ie (не знаю какой, последний).
                                0
                                Ну про HTTP 2.0 я знаю, а вулканизация наверное решит проблему с лишними сетевыми запросами, и всё же что с рендрингом?
                                Ведь если у нас возникает css где то в центре html то браузер не показывает картинку пока этот css не скушает.
                                Или с JS, если инициализация компонента будет долгой, то пользователь увидит всё до компонента, потом будет тупняк и пользователь увидит всё после компонента? Я знаю что есть всякие defer и прочее, но как это реализовано тут?
                                К примеру скорость работы gmail, adsense, analytics меня не очень устраивает, я знаю что это ещё не веб компоненты но автор тот же.
                                  0
                                  Посмотрите их демо www.polymer-project.org/apps/topeka/
                                    0
                                    Спасибо, интересно. В Chrome работает достаточно шустро, а в firefox лагает.
                                    Глянул инспектор… хм… html на 800 килобайт (200 сжатый) со всем всем… а как же кеширование? Но опять же, это single page и web app.
                                      0
                                      FF нету. IE 11 на ноуте(i5) почти не лагает, я бы сказал не критично. Есть некоторые проблемы в верстке, особенно с «выезжанием окон». Но в целом работать можно. Про хром сказали.
                                      В примере только статика и данные. А что по вашему не web app?
                                    +1
                                    В polymer есть атрибут unresolved для body, он решает проблему частичной отрисовки, пока страница не готова — она не показывается. Это простое решение. Визуально выглядит как белый фон, потом плавно появляется содержимое. Не мешает совершенно.
                                    Я бы не сказал что прям автор тот же. Да, Google активно продвигает идею, но она основана на стандартах, то есть не является проприетарной, к тому же при нативной поддержке работать будет гораздо быстрее любых шаблонизаторов и подобных вещей.
                                    0
                                    www.polymer-project.org/components/paper-elements/demo.html#paper-menu-button — ужасно тормозит на Firefox 32 linux, хотя в chrome достаточно шустро.
                                      0
                                      они там в iframe подгружают целую страничку с демо (из компонента), оно в хроме часто тупит с этой подгрузкой.
                                • НЛО прилетело и опубликовало эту надпись здесь

                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                  Самое читаемое