如果需要,我们可以在React,Vue甚至jQuery中实现Angular组件

如果您在npm中发现了一个很棒的组件,但是其前缀为ng,ngx,angular等,那么不要为此感到不安。 有很多解决方案来获取此组件。 在本文中,我们将考虑一个由Angular团队正式支持的解决方案,即Angular Elements。

为了练习,请从Awesome Angular中选择任何组件。

我选择了一个简单但非常有趣的ngx-avatar 。 依次显示来自各种社交网络的化身或仅显示用户的姓名缩写。
像这样:


而且他有一个简单的API,这是一个小例子:

<ngx-avatar facebookId="1508319875"></ngx-avatar> <ngx-avatar src="assets/avatar.jpg"></ngx-avatar> <ngx-avatar name="John Doe"></ngx-avatar> 

因此,为此创建一个Angular项目并连接库。

 ng new avatar-lib --minimalN npm i ngx-avatar --save 

将包装连接到我们的模块。

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { AppComponent } from './app.component'; // Import your AvatarModule import { AvatarModule } from 'ngx-avatar'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, // Specify AvatarModule as an import AvatarModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } 

现在让我们创建一个简单的组件,因为默认情况下`AvatarModule`不会导出其唯一的组件。

 ng gc avatar 

 import { Component, ViewEncapsulation, Input } from '@angular/core'; @Component({ selector: 'app-avatar', template: ` <ngx-avatar [name]="name"></ngx-avatar> `, styles: [], encapsulation: ViewEncapsulation.ShadowDom }) export class AvatarComponent { @Input() name: string; constructor() { } } 

为简单起见,我们仅使用输入参数之一。

我们将从所有这些创建通用组件。 为了使我们的元素起作用,您需要将Angular Elements添加到我们的项目中。

 ng add @angular/elements 

除其他外,此命令还将在脚本部分中包括用于注册自定义元素的精简版本。

 "scripts": [{ "input": "node_modules/document-register-element/build/document-register-element.js" }] 

生成的app.module.ts:

 import { BrowserModule } from '@angular/platform-browser'; import { NgModule, Injector } from '@angular/core'; import { createCustomElement } from '@angular/elements'; import { AvatarComponent } from './avatar.component'; import { AvatarModule } from 'ngx-avatar'; @NgModule({ declarations: [AvatarComponent], imports: [AvatarModule, BrowserModule], entryComponents: [AvatarComponent] }) export class AppModule { constructor(private injector: Injector) { //    Angular Element const avatarComponent = createCustomElement(AvatarComponent, { injector }); //     customElements.define('avatar-lib', avatarComponent); } ngDoBootstrap() {} } 

太好了! 现在我们需要收集所有这些东西。 为此,创建自己的收集器,将我们的组件打包到一个js文件中:

 const fs = require('fs-extra'); const concat = require('concat'); (async function build() { const files = [ './dist/avatar-lib/runtime.js', './dist/avatar-lib/polyfills.js', './dist/avatar-lib/scripts.js', './dist/avatar-lib/main.js' ]; await fs.ensureDir('elements'); await concat(files, 'elements/avatar-lib.js'); })(); 

一切准备就绪! 它仍然只是收集。 将这样的脚本添加到我们的package.json中。

 "build:elements": "ng build --prod --output-hashing none && node build.js" 

好吧,就是这样! 我们得到了这样一个js文件`avatar-lib.js`,gzip中的文件重约221kB,约60kb。 自然地,这里有更多的角形 /芯形。 ngx头像本身在gzip中重约16.8kB和5.4kB。 为了大大减轻avatar-lib.js的重量,我们需要Ivy Compiler,但这是另一篇文章的主题。 (我希望Ivy会在这一刻被释放,或者我将从现有的可用资源中手动收集)。

Angular Elements给了我们什么?

这只是用于实现Web组件的便捷api。 实际上,没有它,是可以做的。 看看您之前可以做些什么: Jia Li撰写的一篇文章(现在活跃在Zone.js上)

我们将组件嵌入其他框架中。

Vue的第一名。 我们以对您方便的任何方式进行连接,并将avatar-lib插入模板,通过标准vue bing传输数据。

 <avatar-lib :name = 'myName'></avatar-lib> 

也可以组织输出事件。

Vue演示: https : //github.com/Jamaks/angular-element/tree/master/ang-el-vue

现在是React的时候了! 一切都一样简单:

 <avatar-lib name = {this.myName}></avatar-lib> 

React演示

好吧,总的来说,这个项目

至于目前的浏览器支持:

https://angular.io/guide/elements#browser-support-for-custom-elements
https://developer.mozilla.org/zh-CN/docs/Web/API/CustomElementRegistry/define

当然,由您决定是否使用这种实现方法。 我希望UI组件不要附加到任何东西上并且没有类似的后缀:ng-,ngx-,v-,react-,rc-等。

加分

受组件大小(ngx-avatar)的启发,我仍然尝试提供ngtsc,ngcc,然后使用汇总将其组装。 但是尝试没有成功,因为选定的组件需要许多外部模块。 拼命的,使这个组件看起来很像,结果令人惊喜-在目前(7.1.2),该库在gzip中为〜96kb和〜26kb。 自然,存在很多依赖关系,而我的汇总配置还有很多不足之处。 但是,这不是Ivy演示过程中向我们显示的3kb。 当他们将ngcc部署到Webpack(cli)并编写文档时,这仍然是可以预期的。

您还可以在这里找到来自Angular世界的小型实验和内部人员。

Source: https://habr.com/ru/post/zh-CN432664/


All Articles