本文對 Angular Schematics 進行了介紹,並建立了一個用於建立自定義 Component 的 Schematics ,而後在 Angular 項目中以它爲模板演練了經過 Schematics 添加自定義的 Component 。css
簡單來講,Schematics 是一個項目處理工具,能夠幫助咱們對 Angular 項目中的內容進行成批的處理。html
好比咱們在是使用 Angular CLI 的時候,可能使用過諸如 ng g c myComponent 之類的命令來幫助咱們建立一個新 Component ,這個命令將各類工做成批完成,添加 Component 代碼文件、模板文件、樣式文件、添加到 Module 中等等。node
如今,咱們也能夠本身來建立自定義的 Schematics 。在下面的介紹中,咱們將建立一個自定義的 Schematics,實現這個相似的功能,咱們還提供了命令選項的支持。git
對於 Schematics 的介紹,請參考:Schematics — An Introductiongithub
首先您須要安裝 Schematics 的命令行工具。npm
npm install -g @angular-devkit/schematics-cli
而後,就可使用這個工具來建立您的第一個 Schematics 了,咱們將它命名爲 my-first-schema。json
schematics blank --name=my-first-schema
這會建立名爲 my-frist-schema 的文件夾,在其中已經建立了多個文件,以下所示。架構
咱們使用 blank 爲咱們後繼的工做打好基礎。app
而後,咱們定義本身的 Schematics 。工具
須要將 src 文件夾中的 collection.json 修改爲以下內容:
{ "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", "schematics": { "my-first-schema": { "aliases": ["mfs"], "factory": "./my-first-schema", "description": "my first schematic.", "schema": "./my-first-schema/schema.json" } } }
$schema => 定義該 collection 架構的 url 地址.
schematics => 這是你的 schematics 定義.
my-first-schema => 之後使用這個 schematics 的 cli 名稱.
aliases => 別名.
factory => 定義代碼.
Description => 簡單的說明.
Schema => 你的 schema 的設置. 這個文件的內容應該以下所示。咱們在其中定義了多個自定義的選項,在使用這個 Schematics 的時候,能夠經過這些選項來設置生成的內容。
{ "$schema": "http://json-schema.org/schema", "id": "my-first-schema", "title": "my1er Schema", "type": "object", "properties": { "name": { "type": "string", "default": "name" }, "path": { "type": "string", "default": "app" }, "appRoot": { "type": "string" }, "sourceDir": { "type": "string", "default": "src/app" }, "service": { "type": "boolean", "default": false, "description": "Flag to indicate whether service should be generated.", "alias": "vgs" } } }
這裏能夠設置你的 schematics 的命令選項,相似於在使用 g 來建立一個新的組件的時候,您可使用一個 --change-detection 的選項。
ng g c component-name --change-detection
您還須要爲您的選項建立一個接口 schema.ts。
export interface schemaOptions { name: string; appRoot: string; path: string; sourceDir: string; service: boolean; }
下面纔是咱們的核心內容 index.ts 。這裏定義咱們 schematics 的邏輯實現。
import { chain, mergeWith } from '@angular-devkit/schematics'; import { apply, filter, move, Rule, template, url, branchAndMerge } from '@angular-devkit/schematics'; import { normalize } from '@angular-devkit/core'; import { dasherize, classify} from "@angular-devkit/core/src/utils/strings"; import { schemaOptions } from './schema'; const stringUtils = {dasherize, classify}; function filterTemplates(options: schemaOptions): Rule { if (!options.service) { return filter(path => !path.match(/\.service\.ts$/) && !path.match(/-item\.ts$/) && !path.match(/\.bak$/)); } return filter(path => !path.match(/\.bak$/)); } export default function (options: schemaOptions): Rule { // TODO: Validate options and throw SchematicsException if validation fails options.path = options.path ? normalize(options.path) : options.path; const templateSource = apply(url('./files'), [ filterTemplates(options), template({ ...stringUtils, ...options }), move('src/app/my-schema') ]); return chain([ branchAndMerge(chain([ mergeWith(templateSource) ])), ]); }
Classify is for a little magic in the templates for the schematics.
filterTemplates is a filter for use or add more files.
option.path it’s very important you use this option for create the folders and files in the angular app.
templateSource use the cli options and 「build」 the files into 「./files」 for create you final template (with the cli options changes)
在 my-first-schema 文件夾中,建立名爲 files 的文件夾,添加三個文件:
import { Component, Input, } from '@angular/core'; @Component({ selector: 'my-first-schema-component', templateUrl: './my-first-schema.component.html', styleUrls: [ './my-first-schema.component.css' ] }) export class MyFirstSchemaComponent { constructor(){ console.log( '<%= classify(name) %>' ); } }
這是一個模板文件,其中能夠看到 <%= classify(name) %> 的內容。當你在使用這個 schematics 的時候,classify 將用來獲取 options 中的 name 的值。
my-first-schema.component.html
<% if (service) { %> <h1>Hola Service</h1> <% } %> <% if (!service) { %> <h1>Hola no Service</h1> <% } %>
這裏的 service 一樣來自 options,咱們定義了一個 Boolean 類型的選項。
my-first-schema.component.css,這個文件目前保持爲空便可。
回到控制檯,在你的項目文件夾中執行 build 命令:
npm run build
定義已經完成。
下面,咱們在其它文件夾中,建立一個新的 Angular 項目,以便使用剛剛建立的這個 Schematics。
ng new test-schematics
進入到這個項目中,使用咱們新建立的 schematics。
在其 node-modules 文件夾中建立名爲 mfs 的模塊文件夾,咱們尚未將新建立的 Schematics 上傳到 Npm 中,這裏咱們手工將其複製到新建的 Angular 項目中。
將您前面建立的 schematics 項目中全部的文件(除了 node_modules 文件夾和 package-lock.json 文件以外),複製到這個 mfs 文件夾中,以便使用。
如今,咱們可使用前面建立的這個 schematics 了。
ng g my-first-schema mfs — service — name=」Mfs」 — collection mfs
這裏設置了 name 和 service 的值。
你應該看到以下的輸出:
PS test-schematics> ng g my-first-schema mfs --service --name="Mfs" --collection mfs create src/app/my-schema/my-first-schema.component.css (0 bytes) create src/app/my-schema/my-first-schema.component.html (33 bytes) create src/app/my-schema/my-first-schema.component.ts (320 bytes) PS test-schematics>
在剛纔新建的 Angular 項目 src/app 文件夾中,已經新建了一個名爲 my-first-schema 的文件夾,其中包含了三個文件。
打開 my-first-schema.component.ts 文件,能夠看到替換以後的內容
import { Component, Input, } from '@angular/core'; @Component({ selector: 'my-first-schema-component', templateUrl: './my-first-schema.component.html', styleUrls: [ './my-first-schema.component.css' ] }) export class MyFirstSchemaComponent { constructor(){ console.log( 'Mfs' ); } }
而在 my-first-schema.component.html 中,能夠看到 --service 的影響。
<h1>Hola Service</h1>