发布时间:2018年12月12日
本教程教你如何在Angular应用程序中使用和与Web组件交互。我们将构建一个小型UI,将人们添加到数据网格中。
基础应用
我们使用Angular CLI生成一个新项目。
$ ng new webcomponents
$ cd webcomponents
安装组件
使用web组件的第一步是安装它们。在本例中,我们从Vaadin组件集安装vaadin-text-field
、vaadin-button
和vaadin-grid
。
$ npm install --save @vaadin/vaadin-text-field @vaadin/vaadin-button @vaadin/vaadin-grid
Web Components最常见的是以JavaScript形式发布。在tsconfig.json
根目录下添加以下选项。
{
compilerOptions: {
"allowJs": true
}
}
启用自定义元素
默认情况下,Angular假设所有的自定义HTML元素都是Angular组件,当遇到非angular组件时会抛出错误。你可以通过在应用模块中添加CUSTOM_ELEMENTS_SCHEMA
来启用自定义元素。同时,导入我们用来创建表单的ReactiveFormsModule
。
import { BrowserModule } from '@angular/platform-browser';
-import { NgModule } from '@angular/core';
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
+ import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
- imports: [BrowserModule],
+ imports: [BrowserModule, ReactiveFormsModule],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
为旧版浏览器添加polyfills
虽然大多数现代浏览器都内置了对Web组件的支持,但仍有用户使用旧版浏览器。如果你想让你的应用程序也能为他们所用,你就需要加入polyfills来模拟没有本地支持的浏览器的功能。
webcomponents.js polyfill带有一个加载器脚本,可以用来只加载特定浏览器所需的polyfills。它是动态加载polyfills的,所以不能直接作为Webpack构建的JS依赖项导入。相反,你需要复制这些依赖关系,并在你的索引文件中包含加载器。该库还包含了一个ES5兼容脚本,以备你将你的应用程序移植到ES5中。
$ npm install --save-dev @webcomponents/webcomponentsjs
复制polyfills
你需要复制polyfills来加载它们。你可以通过将它们添加到angular.json
中的assets数组来实现。
"assets": [
"src/favicon.ico",
"src/assets",
+{
+ "glob": "**/*.js",
+ "input": +"node_modules/@webcomponents/webcomponentsjs",
+ "output": "webcomponents/"
+}
装入polyfills
然后,在index.html
的<head>
部分加入加载器和ES5兼容性脚本的可选导入。
<script src="webcomponents/webcomponents-loader.js"></script>
<script>
if (!window.customElements{document.write('<!--');}
</script>
<script src="webcomponents/custom-elements-es5-adapter.js"></script>
<!-- ! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
验证您是否可以用
ng serve
构建应用程序
现在你已经准备好使用web组件了。首先导入app.component.ts
中的组件。同时,导入FormGroup
和FormControl
来构建表单。
import '@vaadin/vaadin-button';
import '@vaadin/vaadin-grid';
import '@vaadin/vaadin-text-field';
import { FormGroup, FormControl } from '@angular/forms';
表格和网格绑定到一个Person
对象。为它创建一个定义。你可以把它放在一个单独的文件中并导入,或者把它内联到app组件文件中。
class Person {
constructor(public firstName: string, public lastName: string) {}
}
最后,将组件的实现替换为以下内容。
export class AppComponent {
people: Person[] = [];
form = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl('')
});
addPerson() {
this.people = [
...this.people,
new Person(this.form.value.firstName, this.form.value.lastName)
];
this.form.reset();
}
}
- 我们的组件状态是一个数组,应该列在网格中的人。
- 一个反应式的FormGroup,带有
firstName
和lastName
的控件。 - 在提交表单时,创建一个新的数组,其中包含一个包含表单中信息的Person对象,然后重置表单。
定义视图HTML
用以下内容替换组件HTML文件的内容。
<form [formGroup]="form" (ngSubmit)="addPerson()">
<vaadin-text-field
label="First Name"
formControlName="firstName"
ngDefaultControl>
</vaadin-text-field>
<vaadin-text-field
label="Last Name"
formControlName="lastName"
ngDefaultControl>
</vaadin-text-field>
<vaadin-button (click)="addPerson()"> Add </vaadin-button>
</form>
<vaadin-grid [items]="people">
<vaadin-grid-column path="firstName" header="First name">
</vaadin-grid-column>
<vaadin-grid-column path="lastName" header="Last name"> </vaadin-grid-column>
</vaadin-grid>
- 将
formGroup
与我们在组件中定义的formGroup绑定,提交到addPerson
方法。 - 除了
formControlName
之外,还要添加ngDefaultControl
。 - 将people数组绑定到网格上的
items
属性。
与标准的Angular表单唯一的区别就是在字段上使用ngDefaultControl
来告诉Angular将自定义字段视为标准文本输入。
小建议:
ngDefaultControl
只对文本输入有效。有一个名为Origami的库,它为Angular中绑定自定义元素作为表单输入提供了更全面的支持。
如果你现在使用ng serve
运行应用程序,你应该有一个使用Web组件的工作应用程序。
结语
一旦你安装了旧浏览器的polyfills,你就可以将Web Components与Angular组件互换使用。在大多数情况下,你会使用Web Components作为叶子节点组件,而Angular用于视图和其他复合组件。
你可以在custom-elements-everywhere.com上阅读更多关于Web组件框架兼容性的信息。