Публикация Адама Боэрема, впервые опубликованная 28 июля 2015 г. для журнала "Purple, Rock, Scissors".

Для всех фронтенд-разработчиков, которые только начали чувствовать себя комфортно с инструментами прошлой недели, недавно на Google I/O было объявлено, что Полимер Google версии 1.0 собирается модернизировать ваше восприятие виджета. Polymer, известный как Веб-компоненты, оптимизирует процесс внедрения стандарта веб-компонентов и добавляет кросс-браузерную поддержку, что делает Polymer практически готовым к работе.

Чтобы дать лучший пример того, почему Polymer и веб-компоненты так хороши, я проведу вас через процесс создания компонента фотопотока с использованием API из нашего приложения GIF-фотобудки Gifn и объясню каждую часть по ходу дела.

Пошаговое руководство

Для начала создайте новую папку в командной строке, используя:

mkdir polymer_tutorial

А затем войдите в папку, используя:

cd polymer_tutorial

Для установки Polymer мы будем использовать Bower, инструмент управления пакетами для JavaScript. Если у вас не установлен Bower, вы можете сделать это с помощью:

npm install -g bower

а затем инициализируйте Bower.

bower init

Оттуда следуйте инструкциям инструмента. Если вы не знаете, как ответить на вопрос, просто нажмите enter и используйте параметр по умолчанию. После инициализации Bower должен поместить файл bower.json в ваш каталог. Чтобы добавить Polymer в качестве зависимости, выполните следующую команду:

bower install --save Polymer/polymer#^1.0.0

Теперь у вас должна быть папка bower_components/ в вашем каталоге, содержащая Polymer и его зависимости. Теперь добавьте два файла в корневой каталог: файл index.html и файл gifn-feed.html, который будет содержать ваш компонент Polymer. Теперь ваш каталог должен выглядеть примерно так:

polymer_tutorial/
    bower_components/
    bower.json
    gifn-feed.html
    index.html

Во-первых, давайте откроем файл index.html и настроим наш HTML для отображения компонента Polymer. Вот весь HTML-код, необходимый для использования простого компонента.

<!doctype html>
<html>
    <head>
        <title>Gifn Polymer</title>
        <script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>
        <link rel="import" href="gifn-feed.html">
    </head>
    <body>
        <gifn-feed event="prplhq"></gifn-feed>
    </body>
</html>

Инициализация компонента в файле index.html состоит из трех основных частей. Сначала вам нужно добавить библиотеку webcomponents:

<script src="bower_components/webcomponentsjs/webcomponents.min.js"></script>

Эта библиотека требуется для всех компонентов Polymer и любых пользовательских компонентов, которые вы создаете самостоятельно. Существует также меньшая библиотека webcomponents-lite.min.js, которую можно использовать вместо нее, если вы создаете элементы только для браузеров, которые в настоящее время поддерживают API веб-компонентов (например, Chrome 36+). . Далее следует тег ссылки, импортирующий наш веб-компонент gifn-feed для использования.

<link rel="import" href="gifn-feed.html">

И затем наш фактический веб-компонент в использовании:

<gifn-feed event="prplhq"></gifn-feed>

Все выглядит вполне нормально, за исключением фактического веб-компонента. Элемент gifn-feed, очевидно, не является вашим обычным HTML, и event="prplhq" также не является ожидаемым атрибутом. Не бойтесь, все это будет иметь смысл, как только мы начнем конкретизировать компонент.

Давайте начнем. Сначала откройте файл gifn-feed.html и добавьте необходимый базовый элемент Polymer вверху файла:

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

Одним из замечательных аспектов Polymer является то, что он позволяет импортировать и расширять элементы очень модульным образом. Помимо необходимого basepolymer.html, вы также можете импортировать iron-ajax.html для простых вызовов Ajax или даже кнопки Material Design с помощью paper-button.html. . Вы можете ознакомиться с некоторыми готовыми к использованию компонентами, созданными Google.

Поскольку gifn-feed будет использоваться в нашем HTML, мы собираемся инициализировать его как модуль DOM следующим образом:

<dom-module id="gifn-feed">
</dom-module>

А теперь самое интересное! Давайте инициализируем компонент Polymer с базовой настройкой внутри тега скрипта.

<dom-module id="gifn-feed">
    <script>
        Polymer({
            is: "gifn-feed",
            properties: {
              event: String
            }
        });
    </script>
</dom-module>

Атрибут «is:» указывает Polymer искать элемент с тегом gifn-feed, а атрибут «properties:» указывает Polymer искать атрибут «event», который будет иметь строковое значение.

Наш веб-компонент по-прежнему ничего не делает, он просто инициализируется. Чтобы добавить действие к компоненту, вы можете использовать один из обратных вызовов жизненного цикла или, в нашем случае, использовать обратный вызов «готово», когда DOM нашего компонента был инициализирован. Вот компонент gifn-feed с «готовым» обратным вызовом.

<dom-module id="gifn-feed">
    <script>
        Polymer({
            is: "gifn-feed",
            properties: {
              event: String
            },
            ready: function() {
                var self = this;
                var xhr = new XMLHttpRequest();
                var baseUrl = 'http://demo.gifn.it';
                self.gifns = [];
                // Send an ajax request to get the gif data
                xhr.open('GET', baseUrl + '/gif/' + self.event);
                xhr.send();
                xhr.onreadystatechange = function() {
                    if(xhr.readyState == 4 && xhr.status == 200){
                        var gifns = [];
                        var response = JSON.parse(xhr.responseText);
                        //Build out the urls for the 5 latest gifs
                        for(var i = 0; i < 5; i++){
                            var gifUrl = baseUrl+'/asset/'+self.event +'/'+ response.gifs[i].slug+'.thumb.gif';
                            gifns.push({ url: gifUrl });
                        }
                        self.gifns = gifns;
                    }
                }
            }
        });
    </script>
</dom-module>

Что мы делаем в этой готовой функции, так это делаем Ajax-запрос к Gifn API для получения списка изображений GIF. Затем мы создаем URL-адреса и помещаем их в массив, который установлен для нашего объекта Polymer. Позвольте мне объяснить некоторые из наиболее важных аспектов.

var self = this;

Хотя это обычная практика работы с внутренней областью видимости в функциях JavaScript, особенно важно иметь доступ к родительскому объекту Polymer, чтобы можно было привязать данные к представлению. Вот пример его использования:

xhr.open('GET', baseUrl + '/gif/' + self.event);

Эта строка отвечает за инициализацию Ajax-запроса к нашему API, но именно self.event делает ее действительно особенной. Помните атрибут event="prplhq" в нашем теге gifn-feed? Теперь он напрямую связан с нашим объектом Polymer для использования в JavaScript, шаблоне HTML и даже в CSS нашего компонента. Вот еще один пример:

self.gifns = gifns;

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

Теперь, когда у нас есть набор данных, давайте создадим представление для нашего компонента. Над нашим тегом script добавьте

<template>
</template>

Это базовый тег шаблона, необходимый для всех представлений. Внутри тега шаблона вы можете добавить HTML, другие импортированные веб-компоненты Polymer и даже некоторые специальные вспомогательные элементы, используемые для операторов if и перебора данных. Поскольку у нас есть массив URL-адресов, давайте добавим вспомогательный тег dom-repeat.

<template>
    <template is="dom-repeat" items="{{gifns}}">
        <img src="{{item.url}}" />
    </template>
</template>

Обратите внимание на значение {{gifns}} в теге элементов? Так вы напрямую получаете доступ к атрибутам, привязанным к вашему объекту Polymer. Поэтому, если вы хотите, вы также можете добавить заголовок для события, например:

<h1>{{event}}</h1>

В случае со специальным элементом dom-repeat требуется атрибут «items», который ссылается на значение массива. Затем элемент dom-repeat будет проходить по массиву в цикле, при этом каждое значение будет доступно с использованием переменной «item».

Увидев завершенное представление, некоторые из вас могут задаться вопросом, почему я решил сделать эту конкатенацию строк беспорядочной в готовой функции.

for(var i = 0; i < 5; i++){
    var gifUrl = baseUrl + '/asset/' + self.event  + '/' + response.gifs[i].slug + '.thumb.gif';
    gifns.push({ url: gifUrl });
}

Вы все, вероятно, согласитесь, что это лучший и более чистый вариант.

<template is="dom-repeat" items="{{gifns}}">
    <img src="https://demo.gifn.it/asset/{{event}}/{{item.slug}}.thumb.gif" />
</template>

Однако в настоящее время это невозможно и, вероятно, является одним из самых больших недостатков построителя шаблонов в Polymer 1.0. Конкатенация строк и пробелы с переменными представления в настоящее время не поддерживаются в Polymer. Каждый элемент должен занимать все пространство элемента представления или все пространство строки в атрибуте.

Например, это будет работать:

<h1>Welcome <span>{{name}}</span></h1>

но этого не будет:

<h1>Welcome {{name}}</h1>

Чтобы завершить представление, мы добавим немного CSS в наш компонент, чтобы сделать его немного более красивым. Давайте добавим этот блок стилей над тегами нашего шаблона.

<style>
    img {
        display:inline-block;
    }
</style>

Хорошо, может быть, это не это, но я действительно ненавижу плавающие элементы. Еще одна замечательная особенность Polymer заключается в том, что он сохраняет CSS вашего компонента локальным, поэтому вам не нужно беспокоиться о конфликтующих правилах CSS.

И это все! Вот полимерная составляющая целиком.

<link rel="import" href="bower_components/polymer/polymer.html">
<dom-module id="gifn-feed">
    <style>
        img {
            display:inline-block;
        }
    </style>
    <template>
        <template is="dom-repeat" items="{{gifns}}">
            <img src="{{item.url}}" />
        </template>
    </template>
    <script>
        Polymer({
            is: "gifn-feed",
            properties: {
              event: String
            },
            ready: function() {
                var self = this;
                var xhr = new XMLHttpRequest();
                var baseUrl = 'http://demo.gifn.it';
                self.gifns = [];
                // Send an ajax request to get the gif data
                xhr.open('GET', baseUrl + '/gif/' + self.event);
                xhr.send();
                xhr.onreadystatechange = function() {
                    if(xhr.readyState == 4 && xhr.status == 200){
                        var gifns = [];
                        var response = JSON.parse(xhr.responseText);
                        //Build out the urls for the 5 latest gifs
                        for(var i = 0; i < 5; i++){
                            var gifUrl = baseUrl+'/asset/'+self.event+'/'+response.gifs[i].slug+'.thumb.gif';
                            gifns.push({ url: gifUrl });
                        }
                        // Bind the response back to the {{gifns}} repeater
                        self.gifns = gifns;
                    }
                }
            }
        });
    </script>
</dom-module>

Чтобы просмотреть компонент Polymer, вам необходимо разместить его на каком-либо сервере. Это может быть локальный сервер, Vagrant box, MAMP или один из моих фаворитов быстрой командной строки.

python -m SimpleHTTPServer

Наслаждаться!

Рабочую демонстрацию можно увидеть по адресу http://polymer.gifn.it, а весь исходный код можно просмотреть на моем GitHub по адресу https://github.com/adamboerema/polymertutorial.

Для получения дополнительной документации см.:

Если вам понравилась эта статья, написанная для цифрового креативного агентства Orlando Purple, Rock, Scissors, пожалуйста, нажмите на сердце ниже, чтобы порекомендовать ее другим!