ngalain下拉选择异步数据搜索异步数据及初始化默认选中数据

在做CURD时使用ng-alain的SF,实现业务功能是相当的快。但是在做一些复杂或者相对复杂的需求时,官方所提供的示例也不一定会有,因此需要自己动手研究及解决。 场景ng-alain 7.2.0新增界面: SF组件使用select小部件下拉里显示懒加载一部分数据(因为数据量大,因此只加载100),搜索时也使用懒加载数据编辑界面:SF组件使用select小部件实始化默认选中的数据,选中的数据有可能不存在懒加载一部分数据。 实现方案:asyncData懒加载数据,并且初始化时插入所需要的数据项,提供默认选中项onSearch进行搜索异步数据。代码来自 项目中的代码片段 ui: SFUISchema = { $repoId: { widget: 'select', placeholder: '请选择', allowClear: true, serverSearch: true, // 懒加载数据,利用管道,插入数据项 // 如果是编辑状态 addSelectOption方法进行判断,插入已选中数据项。 // 方法getRepositoryOfOptionData返回的是observable asyncData: () => this.shareDataService.getRepositoryOfOptionData().pipe(map( (value: any) => { return this.addSelectOption(value); } )), // 搜索时进行懒加载 onSearch: (keyword: string) => this.shareDataService.getRepositoryOfOptionData(keyword).toPromise(), }, // ...}/** * 业务逻辑,判断编辑状态下,是否需要插入已选中数据 * 插入一条下拉选项数据 * @param optionList 下拉数据 */addSelectOption(optionList: any[]) { const option = {}; if (true) { // 加上你的判断条件 option['label'] = '下拉项文字'; // option['value'] = '下拉项的值'; // // 判断数据是否已存在 const isExist = optionList.some((item) => { return item.value == option['value']; }); if (!isExist) { optionList.push(option); } } // 返回所有数据项 return optionList;}shareDataService ...

June 24, 2019 · 1 min · jiezi

ngalain-SF表单项实现行内排列

场景使用ng-alain的SF动态表单,当使用的表单项极少时,通常会使用到inline行内排列,用input组件没啥问题。但是使用某些组件,存在数据异步加载且没有初始值的情况,则ui展现会出现不雅观的问题。如下图。 解决方式在ui中增加width属性即可,如下图示 不需要设置下面这些属性 最终能实现想要的效果

June 21, 2019 · 1 min · jiezi

ngalain动态表单SF表单项设置必填和正则校验

在使用动态表单时对表单项进行非空校验及正则校验。使用手机号进行校验,示例如下:动态表单的基本使用:https://ng-alain.com/form/get... 基于基本示例,增加手机号必填与正则校验的例子: @Component({ selector: 'app-home', template: ` <sf [schema]="schema" [ui]="ui" (formSubmit)="submit($event)"></sf> `})export class HomeComponent { schema: SFSchema = { properties: { email: { type: 'string', title: '邮箱', format: 'email', maxLength: 20 }, name: { type: 'string', title: '姓名', minLength: 3 }, mobileNumber: { type: 'string', title: '手机号', pattern: '^1[0-9]{10}$' }, }, }; ui: SFUISchema = { '*': { spanLabelFixed: 100, grid: { span: 24 }, }, $mobileNumber: { widget: 'string', errors: { 'pattern': '请输入11位手机号码' } } }; submit(value: any) { }}

June 11, 2019 · 1 min · jiezi

Angular代码风格

写在前面自身的良好编码风格只能律己,而无法律人;我喜欢 Angular 其中主要一个因素是有一整套的工具及风格指南,它可以极大的简化团队开发沟通成本,但是有些小缺失例如在编码风格上官方只提供 TypeScript 的部分,对于其他文件并没有一套指南以及智能化。 VSCode 是我开发 Angular 应用的首选,本文也将以此 IDE 为基准;任何提到的扩展都可以通过市场来获取。 Angular 应用是由组件树组成,一个组件从文件来看包含:TypeScript、HTML、Less(或其他 CSS 预处理器),其中 HTML 可能被包含至 ts 文件里。 当然除此之外还包含一些 JSON 文件、Bash 文件等,当此部分不在本文讨论内。TSLintAngular 创建后就已经包含 tslint.json(它是 TSLint 的配置文件),并且所有默认规则都按官方风格指南具体践行。 而 TSLint 的配置文件,默认使用内置预设 tslint:recommended 版本,并在此基础上加入 Angular 质量检查工具 codelyzer,所有这些规则你可以通过 tslint rules、codelyzer 找到每项规则的说明。 规则的写法要么是 boolean 类型,或者使用数组对该规则指定额外参数。运行 ng lint 命令时,当你某个字符串变量使用双引号,它会提示: ERROR: /src/app/app.component.ts[9, 16]: " should be '我们也可以安装 TSLint 扩展让这个触发机制放在正在编码过程中实时反馈: 当有不符合风格指南会出现一个绿色的波浪线,按 command+. > Fix: " Should be '通过终端 PROBLEMS 面板查看所有已打开文件且不符合风格指南的明细嗯,让你按五次 command+. 快捷键,我一定会疯掉;TSLint 扩展支持在保存文件时自动修复,只需要在项目根目录 .vscode/settings.json 配置: ...

May 29, 2019 · 3 min · jiezi

ngalain重置表单cascader不生效

ng-alain 使用SF formReset重置搜索表单时,级联组件cascader不生效,文字没被清空?在使用ng-alain生成的列表模板中,上面是由动态表单组件SF构成。下面是由ST表格组件构成。下面说说ST表格的上方的搜索表单组件SF。 在使用过程中,SF动态表单可以随意配置已有的小部件,大多小部件都很实用并且常用,但有个别小部分存在缺陷问题,如cascader级联组件。你可能会遇到以下的小问题: 当表单都存在数据时,进行重置操作,使用SF的(formReset)方法,但出来的效果除了级联组件cascader内容没清空外,其他小部件都清空了原有的值。此时再调用SF的(formSubmit)方法,发现原来cascader的值是空的,而组件所显示文字却没有被清空。 此时解决办法如下:在(formReset)方法中刷新SF的schema来实现清空。 html文件 <page-header [action]="phActionTpl" [breadcrumb]="breadcrumb"></page-header><nz-card> <sf #sf mode="search" [schema]="searchSchema" [ui]="uiSchema" [button]="sfButton" (formSubmit)="search($event)" (formReset)="reset($event)"></sf> <st #st [data]="url" [columns]="columns"></st></nz-card>ts文件 /** * 搜索 * @param event 搜索表单数据对象 */search(event) { console.log(event) this.st.load(undefined, event)}/*** 搜索重置 * @param event 搜索表单数据对象 */reset(event) { this.st.reset(event); // 针对级联组件cascader不能清空的问题,重新refresh一次表单 this.sf.refreshSchema();}

May 16, 2019 · 1 min · jiezi

使用ng-zorro图标库部分图标不能正常显示

在ng-alain中,使用ng-zorro图标库,发现部分能正常显示,部分并不能显示,在控制台同时发现出错报错。ERROR Error: [@ant-design/icons-angular]: the icon redo-o does not exist or is not registered.at IconNotFoundError (ant-design-icons-angular.js:159)at MapSubscriber.project (ant-design-icons-angular.js:343)...出现以上问题是没有对相对的图标进行导入,并导出。ng-alain默认只导入了图标库的几十个图标,在 style-icons-auto.ts可进行查看。 因此可以参考style-icons-auto.ts,把你所需要的图标进行import and exportng-zorro图标库:https://ng.ant.design/compone...

April 22, 2019 · 1 min · jiezi

angular组件样式不生效

在本周的项目中有一个需求,对处于两种不同状态的计算机列表赋予不同的颜色方便更加醒目的区分,完工后的效果如下。解决思路——rowClassName项目使用了ng-alain,作者提供了许多方便的方法与属性,所以解决这个问题并不太难,张喜锁学长直接给我说了使用rowClassName这个属性。0开始的时候我以为这个类名是对象那个类,还在思考应该怎么写,后来听张喜硕学长一说才明白,这是css的那个类,那就简单了。再写出相应的判断方法/** * @Description: 设置行背景 * 返回class名 */ public setRowColor(record: Host, index: number) { if (record.status === 1) { return ‘greenRow’; } }css.greenRow { background-color: #52c41a;}大功告成,查看测试效果——没有效果……怎么回事?难道思路是错的?打开开发者工具,class已经附上了,但是却没有相应的css失败的原因我猜测产生上面这种现象的原因是,是因为组件的样式进行了封装,而这种给他css的方式时,它没有引用相应的css的文件如果猜测有误,请指出,不胜感激。关于封装封装模式有三种,分别是:Native 原先浏览器Shadow DOM行为。Emulated 仿真模式,通过Angular来模拟类似Shadow DOM的行为。None 无任何封装行为。想更加深入的了解,可以看这篇文章。解决办法难道我们没有办法侵犯第三方组件了吗?好在 Angular 提供了一种对未来工具更好兼容性的命令 ::ng-deep 来强制样式允许侵入子组件。css修改如下:::ng-deep .greenRow { background-color: #52c41a;}成功了(写到这里不得不提一句,实际上要完成需求根本不需要这样麻烦,ng-alain内部已经提供了颜色的样式, 直接使用即可。)Shadow DOMangualr的实际上是Shdow Dom.Shadow DOM它允许在文档(document)渲染时插入一棵DOM元素子树,但是这棵子树不在主DOM树中。因此开发者可利用Shadow DOM 封装自己的 HTML 标签、CSS 样式和 JavaScript 代码。关于Shadow DOM的具体部分可以看这篇文章神奇的Shadow DOM

March 15, 2019 · 1 min · jiezi

Release ng-alain 2.0

从计划2.0开始足足进行近四个月,其中发布过八个版本。当初给2.0做的愿景基本上达到要求,当然一切都还是那句话:【让开发者更加专注于业务】。ng-zorro-antd 提供的大量的基础组件,当你熟悉这些组件以后,开发 Angular 会是一种“爽”体验,然而对于中后台而言部分高频繁组件在大多数场景下显得有点臃肿。所以 2.0 变更主要从两个方面:使 CURD 操作更“自然”开发体验更友好响应式开发CURD提供一组 Simple 系列组件:sv:查看se:编辑st:数据表格(原 simple-table 重新重构)以及基于 JSON Schema 的动态表单 sf,这四个 Simple 系列组件相比较 ng-zorro-antd 的原始写法,更易编写、阅读,基本上可以满足大多数场景;但它们并非用来替代原始的写法,特别是 st 与 sf 它们并不适合复杂交互,此时,依然应该优先使用原始方式。除此之外,2.0 对部分输入属性及接口的多态性、内聚性做一些变更。属性多态性当构建一个数据表格时,表格的数据源可能来自远程数据或本地静态数据,但我们不应该过度的将数据源做成两个不同属性加以区分,他们只是不同的数据来源而已,但对于表格而言是统一:<table [data]=“url”></table><table [data]=“list”></table>属性内聚性同一个功能的属性应该更内聚,例如我们表述一个HTTP请求时,包含:请求方法、请求域、参数等,这些属性应该统一在一个对象值体现,HttpClient 请求就是一个非常好的例子。<st [reqMethod]="‘GET’" [reqParams]="{ a: 1 }"></st><st [req]="{ method: ‘get’, params: { a: 1 } }"></st>响应式开发意指开发过程中如何使用最小的方式构建符合移动端的中后台,ng-alain 默认提供一套 响应式服务 规则,它服务于最基础的CURD组件:se、sv 等。例如:当你希望构建一行两列的表单,并且若屏幕小于 <576px 将自动转化成一列,则只需要这样:<div se-container=“2”> <se label=“Field1”></se> <se label=“Field2”></se></div>当然这一切只是简化 nz-row、nz-col 的运用而已,如果你希望布局也延续这种方式可以使用 sg 组件。除此之外,ng-alain 也将 CSS 做为开发语言非常重要的组成部分,并且将这些语言特征转化成独立的单元类,如果你是采用 VSCODE 可借由 ng-alain snippets 提供的智能提醒,减少理解它们的成本。升级Angular Cli 提供的 ng update 命令让我们可以大胆重构、改进你的组件,并且用户升级只需要简单的一行命令就可以完全升级。从 1.x 升级至 2.x 虽然无法改变 ts 代码方面的动作,但基本上可以完成 HTML 方面的升级,主要还是 ts 代码的解析无法像 HTML 那样预期。而 ng-alain 的 1.x 升至 2.0 也只需要一行命令而已,有关更多细节,请参考升级指引。未来直到 ng-zorro-antd 下一大版本更新之前,2.0 保持一段时间的休息期,不再会有新功能。之后,会根据 ng-zorro-antd 的进度,对 ng-alain 做一次大的性能重构。新尝试ng-alain 正在尝试提供商业主题服务,有兴趣可以参阅。(完) ...

November 21, 2018 · 1 min · jiezi

如何更好使用 ng-zorro-antd 图标

自 ng-zorro-antd 1.7.x 以后图标发生破坏性变更,虽然带了诸多优势,同时也带来几个劣势:若采用动态加载会产生额外的HTTP请求若静态加载需要逐一注册图标st 组件的 format 参数无法直接指定图标ng-alain 默认使用静态加载的做法,毕竟后端使用图标相对于比较有限,即使将 svg 都打包进脚本相比较之前整个 styles 体积上是所有减少,但比较并不多。而针对以上问题,ng-alain 提供几种方案。使用icon插件(推荐)尽可能从项目中分析并生成静态 Icon,插件会自动在 src 目录下生成两个文件:src/style-icons.ts 自定义部分无法解析(例如:远程菜单图标)src/style-icons-auto.ts 命令自动生成文件自动排除 ng-zorro-antd 和 @delon 已经加载的图标。ng g ng-alain:plugin icon同时,需要手动在 startup.service.ts 中导入:import { ICONS_AUTO } from ‘../../../style-icons-auto’;import { ICONS } from ‘../../../style-icons’;@Injectable()export class StartupService { constructor(iconSrv: NzIconService) { iconSrv.addIcon(…ICONS_AUTO, …ICONS); }}有效语法<i class=“anticon anticon-user”></i><i class=“anticon anticon-question-circle-o”></i><i class=“anticon anticon-spin anticon-loading”></i><i nz-icon class=“anticon anticon-user”></i><i nz-icon type=“align-{{type ? ’left’ : ‘right’}}"></i><i nz-icon [type]=“type ? ‘menu-fold’ : ‘menu-unfold’” [theme]=“theme ? ‘outline’ : ‘fill’"></i><i nz-icon [type]=“type ? ‘fullscreen’ : ‘fullscreen-exit’"></i><i nz-icon type=”{{ type ? ‘arrow-left’ : ‘arrow-right’ }}"></i><i nz-icon type=“filter” theme=“outline”></i><nz-input-group [nzAddOnBeforeIcon]=“focus ? ‘anticon anticon-arrow-down’ : ‘anticon anticon-search’"></nz-input-group>动态加载动态加载,这是为了减少包体积而提供的方式。当 NG-ZORRO 检测用户想要渲染的图标还没有静态引入时,会发起 HTTP 请求动态引入。你只需要配置 angular.json 文件:{ “assets”: [ { “glob”: “**/*”, “input”: “./node_modules/@ant-design/icons-angular/src/inline-svg/”, “output”: “/assets/” } ]}动态使用不管是静态或动态加载,依然无法解决原始方法 class=“anticon anticon-” 的便利性,毕竟字符串就是字符串并非 Angular 模板无法被解析,而针对这个问题,提供两种解决办法。类样式事实上所有 Antd 图标都可以在 iconfont 找得到,可以点选自己需要的图标并生成相应的 css 文件或 cdn,最后在项目中可以直接使用 1.7.0 之前的写法。注意: 在项目编辑里加上 anticon anticon- 前缀才能同之前的类名保持一致。// angular.json"styles”: [ “src/iconfont.css”],如果非cnd还需要将相应的 icon 图标文件复制到 assets 目录下,同时修改 iconfont.css 中 @font-face 对应的 url 路径。@angular/elements动态加载的另一种方式是使用 @angular/elements,只需要 nz-icon 指令重新封装成组件。import { Component, Input } from ‘@angular/core’;@Component({ selector: ’nz-icon’, template: &lt;i nz-icon [type]="type"&gt;&lt;/i&gt;,})export class IconComponent { @Input() type: string;}同时在根模块里注册它。import { createCustomElement } from ‘@angular/elements’;@NgModule({ declarations: [], entryComponents: []})export class AppModule { constructor(injector: Injector) { customElements.define(’nz-icon’, createCustomElement(IconComponent, { injector })); }}最后。@Component({ selector: ‘app-demo’, template: &lt;div [innerHTML]="value"&gt;&lt;/div&gt; ,})export class DemoComponent { constructor(private san: DomSanitizer) { } value = this.san.bypassSecurityTrustHtml( icon: &lt;nz-icon type="bell"&gt;&lt;/nz-icon&gt;, );}结论本文只是针对这一次 ng-zorro-antd 图标上的变更做一个总结,就我个人而言还是比较推荐静态加载的方式,这无关乎包体大小的问题,而是更加明确我需要什么所以我应加载什么。 ...

October 26, 2018 · 1 min · jiezi

浅淡 RxJS WebSocket

引言中后台仪表盘是一个非常复杂,特别是当需要全面屏运用时,数据的实时性需求非常高。WebSocket 不管在什么环境中使用其实都是非常简单,各现代浏览器实现标准都很统一,而且接口也足够简单。即便是在 Angular 也是如此,只需要简单几行代码就能使用 WebSocket。const ws = new WebSocket(‘wss://echo.websocket.org’);ws.onmessage = (e) => { console.log(‘message’, e);}若需要向服务端发送消息,则:ws.send(content);在 Angular 里绝大多数的人都会根据上述代码进一步拓展,比如统一消息解析、错误处理、多路复用等,并最终将其封装成一个服务类。事实上,RxJS 也包裹了一个 WebSocket Subject,位于 rxjs/websocket。如何使用假如将上面的示例使用 RxJS 来写,则:import { webSocket, WebSocketSubject } from ‘rxjs/webSocket’;const ws = webSocket(‘wss://echo.websocket.org’);ws.subscribe(res => { console.log(‘message’, res);});ws.next(content);webSocket 是一个工厂函数,所生产出来的 WebSocketSubject 对象可被多次订阅,若未订阅或取消最后一个订阅时都会导致 WebSocket 连接中断,当再一次订阅时会重新自动连接。WebSocketSubjectConfigwebSocket 除了接收字符串(WebSocket服务远程地址)外,还允许指定更复杂的配置项。默认情况下,消息是使用 JSON.parse 和 JSON.stringify 对消息格式序列化和反序列化操作,所以不管消息发送或接收都以 JSON 为准,可通过 serializer、deserializer 属性来改变。若需要关心 WebSocket 什么时候开始或结束(closeObserver),则:const open$ = new Subject();const ws = webSocket({ url: ‘wss://echo.websocket.org’, openObserver: open$});// 订阅打开事件open$.subscribe(() => {});消息WebSocketSubject 也是 Subject 的变体之一,因此订阅它表示接收消息,反之则利用 next、complete、error 来维护消息的推送。使用 next 来发送消息使用 complete 会尝试检测是否最后一个订阅,若是将会关闭连接使用 error 相当于原始 close 方法且必须提供 { code: number, reason?: string} 参数,注意 code 务必遵守取值范围可被重放调用 next 发送消息时若 WebSocket 连接中断(例如:没人订阅时),消息会被缓存当下一次重新连接以后会按顺序发送。这对于异步世界里非常方便,我们只需要确保 Angular 启动前初始化好 WebSocket 不管什么时候订阅接收消息,都可以随时发送也无须等待。事实上这一点是 RxJS WebSocket 默认情况下是通过 webSocket 所生产的 WebSocketSubject 其本质上是 ReplaySubject 的“重放”能力。当然你可以通过 webSocket 的第二个参数改变这种行为。多路复用一般来说我们不太可能只会一个 Web Socket 服务完成所有的事,然而也不太可能针对每一个业务实例创建一个 webSocket。往往我们会增加一层网关并将这些业务 WebSocket 进行汇总,对于前端始终只需要一个连接,这就是多路复用存在的意义。而核心是必须要让后端知道,什么时候发送什么消息给什么样的服务。首先必须先使用 multiplex 方法来创建 Observable 以便订阅某一路消息,它有三个参数来帮助我们区分消息:subMsg 告知正在订阅哪一路消息unsubMsg 告知取消订阅哪一路消息messageFilter 过滤消息,使订阅者只接收哪一路消息const ws = webSocket(‘wss://echo.websocket.org’);const user$ = this.ws.multiplex( () => ({ type: ‘subscribe’, tag: ‘user’ }), () => ({ type: ‘unsubscribe’, tag: ‘user’ }), message => message.type === ‘user’);user$.subscribe(message => console.log(message));const todo$ = this.ws.multiplex( () => ({ type: ‘subscribe’, tag: ’todo’ }), () => ({ type: ‘unsubscribe’, tag: ’todo’ }), message => message.type === ’todo’);todo$.subscribe(message => console.log(message));user$ 流和 todo$ 流他们共用一个 WebSocket 连接,这便是多路复用。虽然订阅是通过 multiplex 创建的,然后消息的推送依然还是需要使用 ws.next()。总结这原本是对内部一个简单培训,然而我发现竟然极少人会讨论 RxJS 里面 Web Socket 的实现。其实一直有想着要给 ng-alain 内置 WebSocket,只是就封装角度来讲完全没有价值,因为已经足够优雅。 ...

September 24, 2018 · 1 min · jiezi

使用 ng-packagr 打包 Angular

写在前面为了让 Angular 类库应用范围更自由,Angular 提出一套打包格式建议名曰:Angular Package Format,包括 FESM2015、FESM5、UMD、ESM2015、ESM5、ES2015 格式,不同格式可以在不同的环境(Angular Cli、Webpack、SystemJS等)中使用。传统方式需要对这些格式逐一打包,一个示例打包脚本写法。这种写法只能针对不同项目的配置,而且除非你了解这些格式的本质否则很难维护;后来社区根据 APF 规范实现了类库 ng-packagr,通过简单的配置可以将你的类库打包成 APF 规范格式。至 V6 以后 Angular Cli 也基于 ng-packagr 实现了另一个 @angular-devkit/build-ng-packagr 应用构建器。如何使用既然 ng-packagr 被 Angular Cli 内置,这让我们进一步简化了生产一个 APF 规范格式的类库的成本。在 Angualr Cli 里使用 ng g library 来创建一个类库模板,例如在一个新的 Angular 应用里执行:ng g library <library name>而打包,则:ng build <library name>最终,将生成的 dist/<libary name> 目录下文件上传相应包管理服务器(例如:npm)提供给其他 人使用。配置说明由 Angular Cli 生成的类库模板大部分内容同 Angular 应用一样,只是多了一个 ng-package.json 的配置文件(对于生产环境是 ng-package.prod.json),它是专门针对 ng-packagr 的一个配置文件,如同 angular.json 一般也是基于 JSON Schema 格式,因此可以通过访问 ng-package.schema.json 了解所有细节,以下描述一些重点项。whitelistedNonPeerDependenciesng-packagr 默认会根据 package.json 的 peerDependencies 节点清单来决定类库所需要第三方依赖包,这些依赖包是不会被打包至类库。然而,所依赖包不存在 peerDependencies 节点里时(当然建议需要依赖的项应该在里面),就需要该属性的配置。lib/entryFile指定入口文件。lib/umdModuleIdsUMD 格式采用 rollup 打包,当类库需要引用一些无法猜出正确 UMD 标识符时,就需要你手动映射这些类库的标识。“umdModuleIds”: { “lodash”: “_"}angular.jsonAngular Cli 配置文件 angular.json 内会增加一个以 <libary name> 命名的构建配置,绝大多数配置性同普通 Angular 应用如出一辙,唯一不同的是 builder 节点为:“builder”: “@angular-devkit/build-ng-packagr:build"次级入口有时候一个类库可能会包含着多个二次入口,就像 @angular/core 类库包含着一个 @angular/core/testing 模块,它只是运用于测试,因此并不希望在项目中引入 @angular/core 时也包含测试代码,但同时二者又是同一个功能性时,这种次级导入显得非常重要。另一种像 ngx-bootstrap、@angular/cdk/ally 等都提供次级模块的导入,可以更好的优化体积。不论出于何种目的,都可以通过 Angular Cli 简单的文件组织进一步打包出主、次级分明的类库。ng g library 生成的结构大概如下:<libary name>├── src| ├── public_api.ts| └── lib/.ts├── ng-package.json├── ng-package.prod.json├── package.json├── tsconfig.lib.json└── tsconfig.spec.json当根目录下包含 README.md、LICENSE 时会自动被复制到 dist 目录中,Npm 规定必须包含 README.md 文件,否则访问已发布类库页时会有未找到描述文件错误提示。若想创建一个 <libary name>/testing 的次级入口,只需要在 <libary name> 根目录下创建一个 testing 目录:<libary name>├── src| ├── public_api.ts| └── lib/.ts├── ng-package.json├── ng-package.prod.json├── package.json├── tsconfig.lib.json├── tsconfig.spec.json└── testing ├── src | ├── public_api.ts | └── .ts └── package.json核心是需要提供一个 package.json 文件,而且内容简单到姥姥家。{ “ngPackage”: {}}最后,依然使用 ng build <libary name>,会产生一个次级导入模块。小结至此,基本上利用 Angular Cli 可以快速的构建一个可发布于 Npm Angular 类库,更复杂的可以构建像 ngx-bootstrap、@angular/cdk/ 类库。自定义构建Angular Cli 虽然提供非常便利的环境,但是对于一些复杂环境像 Delon 类库(ng-alain基建系列类库)包含着多个类库、类库又包含多个次级导入时,Angular Cli 会显得有点啰嗦,特别是对每个类库的 angular.json 配置。其实 @angular-devkit/build-ng-packagr 非常简单,如果将取进一步简化,整个实现差不多相当于:const path = require(‘path’);const ngPackage = require(’ng-packagr’);const target = path.resolve(__dirname, ‘./projects/<libary name>’);ngPackage .ngPackagr() .forProject(path.resolve(target, ng-package.prod.json)) .withTsConfig(path.resolve(target, ’tsconfig.lib.json’)) .build() .then(() => { // 构建完成后干点事 });将上面的代码放到 ./build.js,执行:node scripts/build.js其结果完成是等价。build() 返回的是一个 Promise 对象,意味着可以确保构建开始前和结束后做一点额外的事。总结ng-packagr 极大简化 Angular 类库被打包出一个 APF 规范建议,虽然它以 ng- 开头,但本质上并不一定非要在 Angular 中运用,也可以使用在 React、VUE。 ...

September 20, 2018 · 2 min · jiezi