# Веб-компоненты Сердцем платформы "веб-компоненты" является стандарт [Web Components](http://w3c.github.io/webcomponents/explainer/), который находится в разработке и позволяет описывать свои элементы. [cut] ## Зачем Web Components? Критично настроенный читатель скажет: "Зачем ещё стандарт для создания своих элементов? Я могу создать любой элемент и прямо сейчас! В любом из современных браузеров можно писать любой HTML, используя свои теги. В чём же разница?" Она в том, что обычно элемент с нестандартным названием (например ``) воспринимается браузером, как нечто неопределённо-непонятное. Ему соответствует класс [HTMLUnknownElement](http://www.w3.org/TR/html5/dom.html#htmlunknownelement), и у него нет каких-либо особых методов. **Стандарт Web Components позволяет описывать для новых элементов свои свойства, методы, объявлять свой DOM, подобие конструктора и многое другое.** Давайте посмотрим это на примерах. [warn header="Только Chrome"] Так как спецификация не окончательна, то для запуска примеров рекомендуется использовать Chrome Canary. [/warn] ## Новый элемент Для описания нового элемента используется вызов `document.registerElement(имя, { prototype: прототип })`. Здесь: Вот, к примеру, новый элемент ``: ```html *!* */!* 0 ``` **Метод `registerElement` может быть вызван в любое время, даже и после появления `` в HTML.** Для этого в браузере предусмотрен специальный режим "обновления" существующих элементов. Если браузер видит элемент с неизвестным именем, в котором есть дефис `-` (такие элементы называются "unresolved"), то:
  • Он ставит такому элементу специальный CSS-псевдокласс `:unresolved`, для того, чтобы через CSS можно было показать, что он ещё "не подгрузился".
  • При вызове `registerElement` такие элементы автоматически обновятся до нужного класса.
Вот демо того, что происходит, когда регистрация элемента происходит после его появления в разметке: ```html Hello, world! ``` Создание таких элементов в JavaScript никак не отличается от обычных: ```js var timer = document.createElement('my-timer'); ``` ## Расширение встроенных элементов Для расширения встроенных элементов у `registerElement` предусмотрен параметр `extends`, в котором можно задать, какой тег мы расширяем. Например: ```html ``` Важные детали:
Прототип теперь наследует не от `HTMLElement`, а от `HTMLButtonElement`
Чтобы расширить элемент, нужно унаследовать прототип от его класса.
В HTML указывается при помощи атрибута `is="..."`
Это принципиальное отличие разметки от обычного объявления без `extends`. Теперь `` работать не будет, нужно использовать исходный тег и `is`.
Работают методы, стили и события кнопки.
При клике на кнопку её не отличишь от встроенной. И всё же, это новый элемент, со своими методами, в данном случае `tick`.
При создании нового элемента в JS, если используется `extends`, необходимо указать и исходный тег в том числе: ```js var timer = document.createElement("button", "my-timer"); ``` ## Жизненный цикл Следующие методы автоматически вызываются во время жизненного цикла элемента:
`createdCallback`Элемент создан
`attachedCallback`Элемент добавлен в документ
`detachedCallback`Элемент удалён из документа
`attributeChangedCallback(name, prevValue, newValue)`Атрибут добавлен, изменён или удалён
Как вы, наверняка, заметили, `createdCallback` является подобием конструктора. Можно добавить к элементу свойства, запросить с сервера данные и так далее. Давайте используем `attachedCallback`, чтобы автоматически запускать таймер при вставке в документ: ```html 0 ``` Спецификация:
  • [Introduction to Web Components](http://w3c.github.io/webcomponents/explainer/)
  • [Custom Elements](http://w3c.github.io/webcomponents/spec/custom/)