如果您在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';
现在让我们创建一个简单的组件,因为默认情况下`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) {
太好了! 现在我们需要收集所有这些东西。 为此,创建自己的收集器,将我们的组件打包到一个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-elementshttps://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世界的小型实验和内部人员。