前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Angular Library 快速入门

Angular Library 快速入门

作者头像
阿宝哥
发布2019-11-05 16:09:58
2.3K0
发布2019-11-05 16:09:58
举报

新建 Workspace

$ ng new sf-lib-app
$ cd sf-lib-app
$ ng serve

在介绍如何创建 Angular Library 之前,让我们来看一下 Angular 新的配置文件 —— angular.json。早期版本的 angular-cli.json 文件已经被替换为 angular.json 文件,文件的内容也发生了改变。这里我们关心的 projects 属性,它为每个独立的项目提供了一个入口:

"projects": {
   "sf-lib-app": {
     ...
   },
   "sf-lib-app-e2e": {
     ...
   }
},

这里我们已经有两个项目:

  • sf-lib-app:应用目录;
  • sf-lib-app-e2e:集成 end-to-end 测试。

创建 sf-lib 库

$ ng generate library sf-lib --prefix=sf

这里我们快速总结一下 ng generate library 命令执行的操作:

  • 在 angular.json 文件中添加 sf-lib 项目;
  • 在 package.json 文件中添加 ng-packagr 依赖;
  • 在 tsconfig.json 文件中添加 sf-lib 库的引用;
  • 在项目中的 projects 目录下创建 sf-lib 文件夹。
"sf-lib": {
      "root": "projects/sf-lib",
      "sourceRoot": "projects/sf-lib/src",
      "projectType": "library",
      "prefix": "sf",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": {
            "tsConfig": "projects/sf-lib/tsconfig.lib.json",
            "project": "projects/sf-lib/ng-package.json"
          },
          "configurations": {
            "production": {
              "project": "projects/sf-lib/ng-package.prod.json"
            }
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "projects/sf-lib/src/test.ts",
            "tsConfig": "projects/sf-lib/tsconfig.spec.json",
            "karmaConfig": "projects/sf-lib/karma.conf.js"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "projects/sf-lib/tsconfig.lib.json",
              "projects/sf-lib/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
}

我们来重点关注以下属性:

  • root —— 指向 library 库的根文件夹;
  • sourceRoot —— library 库实际的源码目录;
  • projectType —— 指定项目的类型;
  • prefix —— 指定组件使用的前缀;
  • architect —— 该对象用于配置 Angular CLI 构建流程,如 build、test 和 lint。

另外在 tsconfig.json 文件中,会自动添加以下 paths 信息:

"compilerOptions": {
  "paths": {
   "sf-lib": [
      "dist/sf-lib"
    ],
    "sf-lib/*": [
       "dist/sf-lib/*"
    ]
  }
}

当完成 Angular 库开发后,我们可以通过以下命令进行库的构建:

$ ng build --prod sf-lib

小伙伴们,在构建 Library 时,记得始终添加 —prod 标志。

在应用中使用 sf-lib 库

import { SfLibModule } from "sf-lib";

以上代码能正常导入 Library,是因为 Angular CLI 会优先从 tsconfig.json 的 paths 属性中查找,然后再 node_modules 中查找。

此时的 app.module.ts 文件内容如下:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { SfLibModule } from "sf-lib";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    SfLibModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

然后我们在 app.component.ts 组件对应的模板引用 sf-lib 默认创建的组件:

<sf-sf-lib></sf-sf-lib>

通常情况下,我们会删除默认创建的组件,然后创建自定义组件,下面我们就来介绍如何为 sf-lib 创建自定义组件。

创建 sf-lib 组件

相信 ng generate 命令对于使用过 Angular CLI 的同学来说,都不会陌生。要为 sf-lib 库创建自定义组件,我们也可以使用该命令,唯一需要注意的是就是需要设置 --project 参数:

$ ng generate component button --project=sf-lib

接着从 sf-lib 模块中导出组件:

import { NgModule } from "@angular/core";
import { SfLibComponent } from "./sf-lib.component";
import { ButtonComponent } from "./button/button.component";

@NgModule({
  imports: [],
  declarations: [SfLibComponent, ButtonComponent],
  exports: [SfLibComponent, ButtonComponent]
})
export class SfLibModule {}

之后我们还需要在 public_api 中导出新建的组件:

export * from './lib/button/button.component';

此时我们 public_api.ts 入口文件的内容如下:

/*
 * Public API Surface of sf-lib
 */

export * from './lib/sf-lib.service';
export * from './lib/sf-lib.component';
export * from './lib/button/button.component';
export * from './lib/sf-lib.module';

这里需要说明的是,对于组件来说:设置 @NgModule 的 exports 属性是为了使得元素可见,而添加到public_api.ts 入口文件是为了使得 Class 可见。在完成新建 ButtonComponent 组件的导出工作后,我们需要使用下列命令,重新构建 sf-lib 库:

$ ng build --prod sf-lib

sf-lib 重新构建成功后,我们就可以在模板中使用刚创建的 ButtonComponent 组件:

<sf-sf-lib></sf-sf-lib>
<sf-button></sf-button>

创建 sf-lib 服务

除了创建自定义组件之外,我们也可以创建自定义服务:

$ ng g service data --project=sf-lib

以上命令成功执行后,将在 sf-lib/lib/src 目录下生成一个 data.service.ts 文件:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  constructor() { }
}

假设我们的 DataService 需要利用 HttpClient 从网络上获取对应的数据,这时我们就需要在 SfLibModule 模块中导入 HttpClientModule 模块,且在 DataService 注入 HttpClient 服务:

import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Injectable({
  providedIn: "root"
})
export class DataService {
  constructor(private http: HttpClient) {}
}

在实际开发中,我们可能需要能够灵活配置 DataService 服务中,请求服务器的地址。这里使用过 Angular Router 模块的同学,可能已经想到了解决方案:

@NgModule({
  imports: [HttpClientModule],
  declarations: [SfLibComponent, ButtonComponent],
  exports: [SfLibComponent, ButtonComponent]
})
export class SfLibModule {
  static forRoot(config: SfLibConfig): ModuleWithProviders {
    return {
      ngModule: SfLibModule,
      providers: [
        {
          provide: SfLibConfigService,
          useValue: config
        }
      ]
    };
  }
}

即通过提供 forRoot() 静态方法,让模块的使用方来配置模块中的 provider。示例中 SfLibConfig 接口和 SfLibConfigService token 的定义如下:

export interface SfLibConfig {
  dataUrl: string;
}

export const SfLibConfigService = new InjectionToken<SfLibConfig>(
  "TestLibConfig"
);

注册完 SfLibConfigService provider 后,我们需要更新

import { Injectable, Inject } from "@angular/core";
import { HttpClient } from "@angular/common/http";

import { SfLibConfigService } from "../public_api";

@Injectable({
  providedIn: "root"
})
export class DataService {
  constructor(
    @Inject(SfLibConfigService) private config,
    private http: HttpClient
  ) {}

  getData() {
    return this.http.get(this.config.dataUrl);
  }
}

更新完 DataService 服务,我们来 SfLibComponent 组件中使用它:

import { Component, OnInit } from "@angular/core";
import { DataService } from "./data.service";

@Component({
  selector: "sf-sf-lib",
  template: `
    <p>
      sf-lib works!
    </p>
  `,
  styles: []
})
export class SfLibComponent implements OnInit {
  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService.getData().subscribe(console.log);
  }
}

接着我们在 AppModule 根模块导入 SfLibModule 模块的时候,配置 dataUrl 属性,具体如下:

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, SfLibModule.forRoot({
    dataUrl: `https://jsonplaceholder.typicode.com/todos/1`
  })],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

以上代码成功运行后,你将会在控制台看到以下输出信息:

{userId: 1, id: 1, title: "delectus aut autem", completed: false}

最后在 sf-lib 库开发完成后,我们可以把开发完的库发布到 npm 上:

$ cd dist/sf-library
$ npm publish

参考资源

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/08/24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 新建 Workspace
  • 创建 sf-lib 库
  • 在应用中使用 sf-lib 库
  • 创建 sf-lib 组件
  • 创建 sf-lib 服务
  • 参考资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档