[Web翻译]如何在Angular中使用Web组件

478 阅读2分钟

原文地址:vaadin.com/learn/tutor…

原文作者:medium.com/@marcushell…

发布时间:2018年12月12日

本教程教你如何在Angular应用程序中使用和与Web组件交互。我们将构建一个小型UI,将人们添加到数据网格中。

基础应用

www.youtube.com/watch?v=Wd2…

我们使用Angular CLI生成一个新项目。

$ ng new webcomponents
$ cd webcomponents

安装组件

使用web组件的第一步是安装它们。在本例中,我们从Vaadin组件集安装vaadin-text-fieldvaadin-buttonvaadin-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中的组件。同时,导入FormGroupFormControl来构建表单。

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();
  }
}
  1. 我们的组件状态是一个数组,应该列在网格中的人。
  2. 一个反应式的FormGroup,带有firstNamelastName的控件。
  3. 在提交表单时,创建一个新的数组,其中包含一个包含表单中信息的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>
  1. formGroup与我们在组件中定义的formGroup绑定,提交到addPerson方法。
  2. 除了formControlName之外,还要添加ngDefaultControl
  3. 将people数组绑定到网格上的items属性。

与标准的Angular表单唯一的区别就是在字段上使用ngDefaultControl来告诉Angular将自定义字段视为标准文本输入。

小建议:ngDefaultControl只对文本输入有效。有一个名为Origami的库,它为Angular中绑定自定义元素作为表单输入提供了更全面的支持。

如果你现在使用ng serve运行应用程序,你应该有一个使用Web组件的工作应用程序。

结语

一旦你安装了旧浏览器的polyfills,你就可以将Web Components与Angular组件互换使用。在大多数情况下,你会使用Web Components作为叶子节点组件,而Angular用于视图和其他复合组件。

你可以在custom-elements-everywhere.com上阅读更多关于Web组件框架兼容性的信息。


www.deepl.com 翻译