В этой статье мы создадим пользовательский элемент для формы оплаты кредитной картой, используя библиотеку Polymer . Окончательная форма будет выглядеть примерно так:
Разметка, которая определяет эту форму оплаты, так же тривиальна, как эта:
<credit-card amount="$300"></credit-card>
Как и ожидалось, под этим пользовательским элементом скрыт дополнительный уровень абстракции, который заботится обо всех сложностях, сопровождающих типичную форму оплаты кредитной картой. Использование пользовательского элемента помогает изолировать любые потенциальные будущие проблемы и сохраняет верхний слой разметки чистым и семантическим.
Форма оплаты кредитной картой будет состоять из:
- Адрес электронной почты
- Номер кредитной карты
- Срок годности
- Номер CVC
Если вы никогда ранее не использовали библиотеку Polymer или вам необходимо освежить свои знания об основных понятиях веб-компонентов, то вы можете сначала прочитать мои предыдущие статьи о SitPoint:
Эти статьи должны помочь вам освоиться с минимальными знаниями, необходимыми для понимания этой статьи.
Базовая настройка проекта
Прежде чем мы начнем создавать наш пользовательский элемент, мы быстро настроим папку проекта, установив Polymer и все необходимые зависимости через Bower.
$ bower install --save Polymer/polymer
Это позволит установить библиотеку Polymer и полизаполнения веб-компонента в папке bower_components
.
bower_components/ ├── core-component-page ├── webcomponentsjs └── polymer
Обратите внимание, что после перехода на v0.5.0, polyfill platform.js
был переименован в webcomponents.js
и теперь поддерживается отдельно.
Разработка разметки
Основной подход к созданию пользовательского элемента заключается в том, чтобы сначала решить, как мы собираемся использовать его в нашей разметке, а затем вернуться назад, чтобы создать шаблон пользовательского элемента. В этом случае мы намерены использовать наш пользовательский элемент, указав сумму, подлежащую выплате, с помощью атрибута amount
<credit-card>
,
<credit-card amount="$300"></credit-card>
Мы credit-card.html
с создания файла credit-card.html
в корне папки нашего проекта и импортируем файл polymer.html
, необходимый для определения пользовательского элемента.
<link rel="import" href="bower_components/polymer/polymer.html">
Мы объявим наш новый элемент <credit-card>
с помощью атрибута name
<polymer-element>
:
<polymer-element name="credit-card"> <template> <!-- More to come --> </template> </polymer-element>
Все необходимые стили и разметка, необходимые для разработки нашего пользовательского элемента, будут находиться внутри <template>
. Я использовал стандартные элементы управления формой вместе с соответствующими метками для доступности.
<template> <form> <fieldset name="personalInfo"> <label for="email">Email</label> <input type="email" id="email" placeholder="[email protected]"> </fieldset> <fieldset name="cardInfo"> <label for="cardNum" required>Card Number</label> <input type="tel" id="cardNum" placeholder="0000 0000 0000 0000"> <label for="cardExp" required>Expires</label> <input type="tel" id="cardExp" placeholder="MM/YY"> <label for="cardCVC" required>CVC</label> <input type="tel" id="cardCVC" placeholder="***"> </fieldset> <input type="submit" value="Donate {{amount}}"> </form> </template>
В приведенном выше HTML нет ничего необычного, кроме следующей строки:
<input type="submit" value="Donate {{amount}}">
Значения внутри {{ }}
называются выражениями Polymer. Они предоставляют возможность привязывать данные, указанные в Light DOM (при использовании пользовательского элемента), в Shadow DOM (шаблон пользовательского элемента). В данном случае я имею в виду значение, указанное в атрибуте amount
<credit-card>
:
<credit-card amount="$300"></credit-card>
И это будет переведено на:
<input type="submit" value="Donate $300">
И последнее, что нужно сделать для определения атрибутов в пользовательском элементе, это то, что вам также нужно объявить их в верхней части основного элемента, прежде чем вы сможете их использовать. Это делается следующим образом:
<polymer-element name="credit-card" attributes="amount">
Указывая несколько атрибутов для одного и того же пользовательского элемента, вы можете разделить их через пробел или запятую.
Стилизация пользовательского элемента
Стили могут быть определены в теге шаблона следующим образом:
<template> <style> /* ... */ </style> </template>
Или мы можем записать их в новый файл CSS, а затем импортировать файл с помощью тега link
.
В попытке сделать нашу настройку более модульной и масштабируемой для обработки будущих улучшений, мы будем использовать второй подход, создав новый файл CSS, credit-card.css
, который будет содержать все необходимые стили для нашего пользовательского элемента.
<template> <link rel="stylesheet" href="credit-card.css"> <form> [...] </form> </template>
В этой статье основное внимание уделяется функциональному аспекту пользовательского элемента, а не дизайну. Стилизация довольно стандартна, если вы знаете о следующих моментах:
- По умолчанию все пользовательские элементы установлены как
display: inline
. Следовательно, в этом случае нам пришлось явно объявить наш элемент какdisplay: block
. -
:host
ссылается на сам пользовательский элемент и имеет самую низкую специфичность. Это позволяет пользователям переопределять ваши стили извне.
Регистрация элемента
Регистрация элемента позволяет распознавать его как пользовательский элемент в браузере поддержки. Как правило, элемент можно зарегистрировать напрямую, вызвав конструктор Polymer()
,
Polymer([ tag-name, ] [prototype]);
Где:
-
tag-name
совпадает с атрибутомname
в<polymer-element>
. Это необязательно, если<script>
который вызывает Polymer, не находится вне<polymer-element>
Polymer<polymer-element>
. -
[prototype]
содержит открытые свойства и методы, используемые для определения поведения пользовательского элемента.
Самый простой способ вызвать Polymer — разместить встроенный скрипт внутри <polymer-element>
Polymer <polymer-element>
:
<polymer-element name="tag-name"> <template> [...] </template> <script>Polymer();</script> </polymer-element>
Для элементов, которые не требуют пользовательских свойств или методов, вы можете использовать атрибут noscript
:
<polymer-element name="tag-name" noscript> [...] </polymer-element>
Для краткости мы зарегистрируем наш пользовательский элемент, явно указав имя тега следующим образом:
<script> Polymer('credit-card', { /* More to come */ }); </script>
Использование библиотек JavaScript с пользовательскими элементами
На практике поведение пользовательского элемента может зависеть от внешней библиотеки JavaScript. В этом разделе вы познакомитесь с базовым примером использования внешних файлов JavaScript в сочетании с вашим пользовательским элементом.
Давайте улучшим условия оплаты для наших пользователей:
- Форматирование номера кредитной карты в группы из 4 цифр общей длиной не более 16 цифр.
- Форматирование даты истечения срока в
MM/YY
.
Мы будем использовать превосходную библиотеку jquery.payment
от Stripe, которая решает эти проблемы с юзабилити и, в свою очередь, нуждается в работе библиотеки jQuery. В двух словах, у нас есть два сценария, которые нужно включить прямо перед закрывающим <polymer-element>
, так как нам не нужен JavaScript для загрузки пользовательского элемента.
<polymer-element name="credit-card" attributes="amount"> <template> [...] </template> <script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script> <script src='//cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.1/jquery.payment.min.js'></script> <script> Polymer('credit-card', {}); </script> </polymer-element>
Библиотека Polymer предоставляет набор полезных методов обратного вызова для внедрения настраиваемого поведения на разных этапах жизненного цикла создания настраиваемого элемента:
-
created
— экземпляр элемента создан. -
ready
— экземпляр элемента был вставлен в DOM. -
detached
— экземпляр элемента был удален из DOM. -
attributeChanged
— Атрибут элемента был добавлен, удален или обновлен.
Больше информации о методах жизненного цикла доступно в руководстве разработчика API
<script> Polymer('credit-card', { ready: function() { var cardNum = this.$.cardNum, cardExp = this.$.cardExp, cardCVC = this.$.cardCVC, creditCard = this.$.creditCard, $cardNum = jQuery(cardNum), $cardExp = jQuery(cardExp), $cardCVC = jQuery(cardCVC), $creditCard = jQuery(creditCard); /* Formatting input fields */ $cardNum.payment('formatCardNumber'); $cardExp.payment('formatCardExpiry'); $cardCVC.payment('formatCardCVC'); /* Card validation on Form submission */ $creditCard.submit(function(e){ var cardExpiryVal = $cardExp.payment('cardExpiryVal'), cardType = jQuery.payment.cardType($cardNum.val()), isValidNum = jQuery.payment.validateCardNumber($cardNum.val()), isValidExp = jQuery.payment.validateCardExpiry(cardExpiryVal), isValidCVC = jQuery.payment.validateCardCVC($cardCVC.val(), cardType); if (isValidNum && isValidExp && isValidCVC) { /* Success */ } else { /* Validation failed */ } }); } }); </script>
Polymer предоставляет удобный способ автоматического поиска узлов внутри Shadow DOM, используя this.$.id
. $
конечно это сокращенный псевдоним для jQuery
. Следовательно, чтобы избежать любых потенциальных конфликтов, мы использовали идентификатор jQuery
во всем коде. Кроме того, если вы хотите найти узлы, используя имя класса вместо идентификатора, то у вас есть два варианта:
Получите прямой доступ к Shadow DOM, используя:
this.shadowRoot.querySelector('.classname');
Или добавьте идентификатор ( #container
) в пользовательский элемент и затем используйте:
this.$.container.querySelector('.classname');
Использование пользовательского элемента
Включите файл credit-card.html
в ваш документ, а затем использовать пользовательский элемент так же просто, как написать:
<head> <link rel="import" href="credit-card.html"> </head> <body> <credit-card amount="$300"></credit-card> </body>
Chrome и Opera теперь полностью поддерживают веб-компоненты в своих последних версиях. IE, Firefox и Safari, однако, все еще отстают . Чтобы включить поддержку этих браузеров, необходимо также включить webcomponents.js
webcomponents.js:
<head> <!-- Load platform support before any code that touches the DOM. --> <script src="bower_components/webcomponentsjs/webcomponents.min.js"></script> <link rel="import" href="credit-card.html"> </head>
Ознакомьтесь с полным кодом вместе с демонстрацией на Plunker. Я также создал репозиторий проектов на Github для пользовательского элемента кредитной карты.
Вывод
Это не функциональная форма оплаты кредитной картой и далеко не полная. Тем не менее, демонстрация должна быть достаточно хороша, чтобы дать вам возможность начать создавать собственные компоненты дизайна в виде пользовательских элементов с использованием библиотеки Polymer.