Я пытаюсь интегрировать WebComponents, встроенные в Stencil, в приложение Angular. Таким образом, я бы хотел, чтобы использование компонента выглядело как "angular -подобный", насколько это возможно. Начиная с очень простого компонента с парой строковых свойств, я хотел бы встроить его в мое приложение Angular обычным способом, но, кажется, зашли в тупик. Обратите внимание, что мой фактический компонент намного сложнее, чем этот, но я хотел, чтобы это было достаточно просто, чтобы кто-то мог переварить.
Мой компонент трафарета выглядит так:
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrl: 'my-component.css',
shadow: true
})
export class MyComponent {
@Prop() first: string;
@Prop() last: string;
private getText(): string {
return `${this.first} ${this.last}`;
}
render() {
return <div>Hello, World! I'm {this.getText()}</div>;
}
}
Я публикую sh этот компонент в репозитории npm, а затем в другом каталоге создаю новое (очень простое) приложение Angular (используя angular -cli) и npm установить компонент в это приложение angular. Затем я выполняю обычные обновления до main.ts
(чтобы вызвать определенныеCustomElements) и app.module.ts
(чтобы импортировать CUSTOM_ELEMENTS_SCHEMA), чтобы включить WebComponents (подробности, которые я здесь опущу) Достаточно сказать, что WebComponent правильно создается.
Затем я вставляю веб-компонент в свой angular компонент со следующей строкой в шаблоне компонента Angular и двух строковых свойствах в моем компоненте Angular с именами firstName и LastName:
<my-component [first]="firstName" [last]="lastName"></my-component>
Мой компонент получает первое и последнее свойства, заполненные undefined
. Привязка свойств не работает. Чтобы заставить его работать, я должен использовать привязку атрибутов и настроить свой шаблон следующим образом:
<my-component [attr.first]="firstName" [attr.last]="lastName"></my-component>
Затем он работает как положено - с односторонней привязкой к первому и последнему свойствам в моем компоненте.
Это может показаться относительно незначительной косметикой c, но я думаю, что это имеет другие последствия. Например, если я изменяю одно из свойств (скажем, первое), чтобы иметь изменяемые параметры и параметры отражения, изменения свойства в компоненте не отражаются в angular, даже если вы используете двустороннее связывание: [(attr.first)]="firstName"
. Опять же, есть обходной путь, вы можете объявить событие, которое вы генерируете, со значением каждый раз, когда вы изменяете первое свойство в компоненте:
@Event({ eventName: "first-changed" }) firstChanged: EventEmitter;
Изменение шаблона выглядит так:
<my-component [attr.first]="firstName" [attr.last]="lastName"> (first-changed)="onFirstChanged($event.detail)</my-component>
И, наконец, вы бы изменили компонент Angular, чтобы иметь функцию onFirstChanged:
onFirstChanged(change: string) {
this.firstName = change;
}
Это дает эффект двустороннего связывания и функций, как вы могли ожидать. Однако использование компонента далеко от того, что может ожидать разработчик Angular. И чем больше обходных путей я добавляю, тем менее и менее знакомым будет веб-компонент тем, кто живет в Angular весь день.
Что особенно странно для меня, так это то, что я могу использовать примеры Google по всему Интернету, показывающие Angular встраивание компонентов трафарета, которые используют привязку свойств (и даже один, показывающий двустороннюю привязку), но я не могу ничего сделать из них фактически работают с последними кодами Stencil JS (версия 1.8.8) и Angular (версия 9.0.5).
Есть ли здесь что-то простое, что мне не хватает? Я относительно новичок во всем этом, поэтому любые рекомендации, которые вы можете дать, которые помогут мне разработать веб-компоненты, которые хорошо работают в Angular (но все еще функционируют в React и только в обычном HTML / JS), будут оценены.