Обзор элементов Angular¶
Элементы Angular — это компоненты Angular, упакованные как custom elements (также называемые Web Components), веб-стандарт для определения новых элементов HTML в независимости от фреймворка.
Пример приложения, которое описывается на этой странице.
Пользовательские элементы — это функция веб-платформы, которая в настоящее время поддерживается в Chrome, Edge (на базе Chromium), Firefox, Opera и Safari, и доступна в других браузерах через полифиллы (см. "Поддержка браузеров"). Пользовательский элемент расширяет HTML, позволяя вам определить тег, содержимое которого создается и контролируется кодом JavaScript.
Браузер поддерживает CustomElementRegistry определенных пользовательских элементов, который отображает инстанцируемый JavaScript класс на HTML тег.
Пакет @angular/elements экспортирует API createCustomElement(), который обеспечивает мост от интерфейса компонента Angular и функциональности обнаружения изменений к встроенному API DOM.
Преобразование компонента в пользовательский элемент делает всю необходимую инфраструктуру Angular доступной для браузера. Создание пользовательского элемента является простым и понятным и автоматически соединяет ваше представление, определяемое компонентом, с обнаружением изменений и привязкой данных, отображая функциональность Angular на соответствующие встроенные эквиваленты HTML.
Мы работаем над созданием пользовательских элементов, которые могут быть использованы веб-приложениями, построенными на других фреймворках. Минимальная, самодостаточная версия фреймворка Angular внедряется в качестве сервиса для поддержки функций обнаружения изменений и привязки данных компонента.
Подробнее о направлении развития можно узнать из этой видеопрезентации.
Использование пользовательских элементов¶
Пользовательские элементы загружаются самостоятельно — они автоматически запускаются при добавлении в DOM и автоматически уничтожаются при удалении из DOM. После добавления пользовательского элемента в DOM любой страницы он выглядит и ведет себя как любой другой элемент HTML, и не требует специальных знаний терминов Angular или соглашений об использовании.
| Подробности | |
|---|---|
| Простой динамический контент в приложении Angular | Преобразование компонента в пользовательский элемент обеспечивает прямой путь к созданию динамического HTML-контента в приложении Angular. HTML-контент, который вы добавляете непосредственно в DOM в приложении Angular, обычно отображается без обработки Angular, если вы не определите динамический компонент, добавив свой собственный код для подключения HTML-тега к данным приложения и участия в обнаружении изменений. При использовании пользовательского элемента все эти действия выполняются автоматически. |
| Если у вас есть приложение с большим количеством контента | Если у вас есть приложение с большим количеством контента, например, приложение Angular, в котором представлена эта документация, пользовательские элементы позволят вам предоставить поставщикам контента сложную функциональность Angular, не требуя знания Angular. Например, руководство Angular, подобное этому, добавляется непосредственно в DOM средствами навигации Angular, но может включать специальные элементы типа <code-snippet>, которые выполняют сложные операции. Все, что вам нужно сообщить поставщику контента, — это синтаксис вашего пользовательского элемента. Им не нужно знать ничего об Angular, ни о структурах данных вашего компонента, ни о его реализации. |
Как это работает¶
Используйте функцию createCustomElement() для преобразования компонента в класс, который может быть зарегистрирован в браузере как пользовательский элемент. После регистрации настроенного класса в реестре пользовательских элементов браузера, используйте новый элемент так же, как встроенный элемент HTML в содержимом, которое вы добавляете непосредственно в DOM:
1 | |
Когда ваш пользовательский элемент размещается на странице, браузер создает экземпляр зарегистрированного класса и добавляет его в DOM. Содержание предоставляется шаблоном компонента, который использует синтаксис шаблонов Angular, и отображается с использованием данных компонента и DOM.
Входные свойства в компоненте соответствуют входным атрибутам для элемента.
Преобразование компонентов в пользовательские элементы¶
Angular предоставляет функцию createCustomElement() для преобразования компонента Angular вместе с его зависимостями в пользовательский элемент. Функция собирает наблюдаемые свойства компонента, а также функциональные возможности Angular, необходимые браузеру для создания и уничтожения экземпляров, обнаружения и реагирования на изменения.
Процесс преобразования реализует интерфейс NgElementConstructor и создает класс-конструктор, настроенный на создание самозагружающегося экземпляра вашего компонента.
Используйте встроенную функцию customElements.define() для регистрации настроенного конструктора и связанного с ним тега пользовательского элемента в CustomElementRegistry браузера. Когда браузер встречает тег для зарегистрированного элемента, он использует конструктор для создания экземпляра пользовательского элемента.
Избегайте использования @Component selector в качестве имени тега custom-элемента. Это может привести к неожиданному поведению, поскольку Angular создает два экземпляра компонента для одного элемента DOM: один обычный компонент Angular и второй, использующий пользовательский элемент.
Маппинг¶
Пользовательский элемент хостит компонент Angular, обеспечивая мост между данными и логикой, определенными в компоненте, и стандартными API DOM. Свойства и логика компонента отображаются непосредственно на атрибуты HTML и систему событий браузера.
-
API создания анализирует компонент в поисках входных свойств и определяет соответствующие атрибуты для пользовательского элемента.
Он преобразует имена свойств, чтобы сделать их совместимыми с пользовательскими элементами, которые не различают регистр.
В результирующих именах атрибутов используется строчный регистр, разделенный тире.
Например, для компонента с
@Input('myInputProp') inputProp, соответствующий пользовательский элемент определяет атрибутmy-input-prop. -
Выводы компонентов отправляются как HTML Custom Events, причем имя пользовательского события совпадает с именем вывода.
Например, для компонента с
@Output() valueChanged = new EventEmitter(), соответствующий пользовательский элемент отправляет события с именем "valueChanged", а выдаваемые данные сохраняются в свойствеdetailсобытия.Если вы указываете псевдоним, то используется это значение; например,
@Output('myClick') clicks = new EventEmitter<string>();приводит к диспетчеризации событий с именем "myClick".
Для получения дополнительной информации см. документацию по веб-компоненту Создание пользовательских событий.
Поддержка браузером пользовательских элементов¶
Недавно разработанная функция custom elements Web Platform в настоящее время поддерживается в нескольких браузерах.
| Браузер | Поддержка пользовательских элементов |
|---|---|
| Chrome | Поддерживается нативно. |
| Edge (Chromium-based) | Поддерживается нативно. |
| Firefox | Поддерживается нативно. |
| Opera | Поддерживается нативно. |
| Safari | Поддерживается нативно. |
Чтобы добавить пакет @angular/elements в свое рабочее пространство, выполните следующую команду:
1 | |
Пример: Служба всплывающих окон¶
Раньше, когда вы хотели добавить компонент в приложение во время выполнения, вам нужно было определить динамический компонент, а затем загрузить его, прикрепить к элементу в DOM и подключить все зависимости, обнаружение изменений и обработку событий, как описано в Dynamic Component Loader.
Использование пользовательского элемента Angular делает этот процесс намного проще и прозрачнее, предоставляя всю инфраструктуру и каркас автоматически — все, что вам нужно сделать, это определить вид обработки событий, который вы хотите. Вам все равно придется исключить компонент из компиляции, если вы не собираетесь использовать его в своем приложении.
Следующий пример приложения Popup Service определяет компонент, который вы можете либо загрузить динамически, либо преобразовать в пользовательский элемент.
| Файлы | Детали |
|---|---|
popup.component.ts | Определяет простой всплывающий элемент, который отображает сообщение ввода, с некоторой анимацией и стилизацией. |
popup.service.ts | Создает инжектируемый сервис, который предоставляет два различных способа вызова PopupComponent: как динамический компонент или как пользовательский элемент Обратите внимание, насколько больше настроек требуется для метода динамической загрузки. |
app.module.ts | Добавляет PopupComponent в список declarations модуля. |
app.component.ts | Определяет корневой компонент приложения, который использует PopupService для добавления всплывающего окна в DOM во время выполнения. Когда приложение запущено, конструктор корневого компонента преобразует PopupComponent в пользовательский элемент. |
Для сравнения в демонстрации показаны оба метода. Одна кнопка добавляет всплывающее окно с помощью метода динамической загрузки, а другая — с помощью пользовательского элемента.
Результат один и тот же, отличается только подготовка.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
Типы для пользовательских элементов¶
Общие API DOM, такие как document.createElement() или document.querySelector(), возвращают тип элемента, соответствующий указанным аргументам. Например, вызов document.createElement('a') возвращает HTMLAnchorElement, который, как известно TypeScript, имеет свойство href.
Аналогично, вызов document.createElement('div') возвращает HTMLDivElement, который, как известно TypeScript, не имеет свойства href.
При вызове неизвестных элементов, таких как пользовательское имя элемента (popup-element в нашем примере), методы возвращают общий тип, такой как HTMLElement, потому что TypeScript не может определить правильный тип возвращаемого элемента.
Пользовательские элементы, созданные с помощью Angular, расширяют NgElement (который, в свою очередь, расширяет HTMLElement). Кроме того, эти пользовательские элементы будут иметь свойство для каждого входа соответствующего компонента.
Например, наш popup-element имеет свойство message типа string.
Есть несколько вариантов, если вы хотите получить правильные типы для ваших пользовательских элементов. Предположим, вы создаете пользовательский элемент my-dialog на основе следующего компонента:
1 2 3 4 | |
Самый простой способ получить точную типизацию — привести возвращаемое значение соответствующих методов DOM к нужному типу. Для этого используйте типы NgElement и WithProperties (оба экспортируются из @angular/elements):
1 2 3 4 5 6 | |
Это хороший способ быстро получить возможности TypeScript, такие как проверка типов и поддержка автозаполнения, для вашего пользовательского элемента. Но он может стать громоздким, если он нужен в нескольких местах, потому что вам придется приводить возвращаемый тип в каждом случае.
Альтернативный способ, который требует определения типа каждого пользовательского элемента только один раз, заключается в дополнении HTMLElementTagNameMap, который TypeScript использует для вывода типа возвращаемого элемента на основе его имени тега (для методов DOM, таких как document.createElement(), document.querySelector() и т.д.):
1 2 3 4 5 6 7 | |
Теперь TypeScript может вывести правильный тип так же, как он это делает для встроенных элементов:
1 2 3 4 | |
28.02.2022

