Обзор элементов 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