日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Angular 原理图 Schematics 学习 - 动手开发一个实际的例子

發(fā)布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Angular 原理图 Schematics 学习 - 动手开发一个实际的例子 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

當(dāng) ng add 命令向項目中添加某個庫時,就會運行原理圖。ng generate 命令則會運行原理圖,來創(chuàng)建應(yīng)用、庫和 Angular 代碼塊。

一些術(shù)語:

規(guī)則

在原理圖 中,是指一個在文件樹上運行的函數(shù),用于以指定方式創(chuàng)建、刪除或修改文件,并返回一個新的 Tree 對象。

文件樹

在 schematics 中,一個用 Tree 類表示的虛擬文件系統(tǒng)。 Schematic 規(guī)則以一個 tree 對象作為輸入,對它們進行操作,并且返回一個新的 tree 對象。

開發(fā)人員可以創(chuàng)建下列三種原理圖:

  • 安裝原理圖,以便 ng add 可以把你的庫添加到項目中。
  • 生成原理圖,以便 ng generate 可以為項目中的已定義工件(組件,服務(wù),測試等)提供支持。
  • 更新原理圖,以便 ng update 可以更新你的庫的依賴,并提供一些遷移來破壞新版本中的更改。

下面我們動手做一個例子。

在庫的根文件夾中,創(chuàng)建一個 schematics/ 文件夾。

在 schematics/ 文件夾中,為你的第一個原理圖創(chuàng)建一個 ng-add/ 文件夾。

在 schematics/ 文件夾的根級,創(chuàng)建一個 collection.json 文件。

編輯 collection.json 文件來定義你的集合的初始模式定義。

如下圖所示:

collection.json 文件內(nèi)容如下:

{"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json","schematics": {"ng-add": {"description": "Add my library to the project.","factory": "./ng-add/index#ngAdd"},"my-service": {"description": "Generate a service in the project.","factory": "./my-service/index#myService","schema": "./my-service/schema.json"}} }

下圖高亮行的意思是:執(zhí)行 ng add 時,調(diào)用文件夾 ng-add 下面的 index.ts 文件。

即這個文件:

我們需要在 my-lib 庫的根目錄下的 package.json 里,申明對上圖 collection.json 文件的引用:

ng add 命令的原理圖可以增強用戶的初始安裝過程。可以按如下步驟定義這種原理圖。

(1) 進入 /schematics/ng-add/ 目錄。
(2) 創(chuàng)建主文件 index.ts。
(3) 打開 index.ts 并添加原理圖工廠函數(shù)的源代碼:

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';// Just return the tree export function ngAdd(options: any): Rule {return (tree: Tree, context: SchematicContext) => {context.addTask(new NodePackageInstallTask());return tree;}; }

提供初始 ng add 支持所需的唯一步驟是使用 SchematicContext 來觸發(fā)安裝任務(wù)。該任務(wù)會借助用戶首選的包管理器將該庫添加到宿主項目的 package.json 配置文件中,并將其安裝到該項目的 node_modules 目錄下。

在這個例子中,該函數(shù)會接收當(dāng)前的 Tree 并返回它而不作任何修改。如果需要,你也可以在安裝軟件包時進行額外的設(shè)置,例如生成文件、更新配置、或者庫所需的任何其它初始設(shè)置。

定義依賴類型

如果該庫應(yīng)該添加到 dependencies 中、devDepedencies 中,或者不用保存到項目的 package.json 配置文件中,請使用 ng-add 的 save 選項進行配置

"ng-add": {"save": "devDependencies"}

可能的值有:

  • false - 不把此包添加到 package.json
  • true - 把此包添加到 dependencies
  • “dependencies” - 把此包添加到 dependencies
  • “devDependencies” - 把此包添加到 devDependencies

構(gòu)建你的原理圖

必須首先構(gòu)建庫本身,然后再構(gòu)建 Schematics.

你的庫需要一個自定義的 Typescript 配置文件,里面帶有如何把原理圖編譯進庫的發(fā)布版的一些指令。

要把這些原理圖添加到庫的發(fā)布包中,就要把這些腳本添加到該庫的 package.json 文件中。

假設(shè)你在 Angular 工作區(qū)中有一個庫項目 my-lib。要想告訴庫如何構(gòu)建原理圖,就要在生成的 tsconfig.lib.json 庫配置文件旁添加一個 tsconfig.schematics.json 文件。

新建一個 tsconfig.schematics.json 文件,維護如下的源代碼:

{"compilerOptions": {"baseUrl": ".","lib": ["es2018","dom"],"declaration": true,"module": "commonjs","moduleResolution": "node","noEmitOnError": true,"noFallthroughCasesInSwitch": true,"noImplicitAny": true,"noImplicitThis": true,"noUnusedParameters": true,"noUnusedLocals": true,"rootDir": "schematics","outDir": "../../dist/my-lib/schematics","skipDefaultLibCheck": true,"skipLibCheck": true,"sourceMap": true,"strictNullChecks": true,"target": "es6","types": ["jasmine","node"]},"include": ["schematics/**/*"],"exclude": ["schematics/*/files/**/*"] }

rootDir 指出在你的 schematics/ 文件夾中包含要編譯的輸入文件,即下圖高亮的文件:

outDir 映射到了庫的輸出目錄下。默認(rèn)情況下,這是工作區(qū)根目錄下的 dist/my-lib 文件夾,即下圖這些文件:

要確保你的原理圖源文件會被編譯進庫包中,請把下列腳本添加到庫項目的根文件夾(projects/my-lib)下的 package.json 文件中。

{"name": "my-lib","version": "0.0.1","scripts": {"build": "../../node_modules/.bin/tsc -p tsconfig.schematics.json","copy:schemas": "cp --parents schematics/*/schema.json ../../dist/my-lib/","copy:files": "cp --parents -p schematics/*/files/** ../../dist/my-lib/","copy:collection": "cp schematics/collection.json ../../dist/my-lib/schematics/collection.json","postbuild": "npm run copy:schemas && npm run copy:files && npm run copy:collection"},"peerDependencies": {"@angular/common": "^7.2.0","@angular/core": "^7.2.0"},"schematics": "./schematics/collection.json","ng-add": {"save": "devDependencies"} }

build 腳本使用自定義的 tsconfig.schematics.json 文件來編譯你的原理圖。

copy:* 語句將已編譯的原理圖文件復(fù)制到庫的輸出目錄下的正確位置,以保持目錄的結(jié)構(gòu)。

postbuild 腳本會在 build 腳本完成后復(fù)制原理圖文件。

提供生成器支持

你可以把一個命名原理圖添加到集合中,讓你的用戶可以使用 ng generate 命令來創(chuàng)建你在庫中定義的工件。

我們假設(shè)你的庫定義了一項需要進行某些設(shè)置的服務(wù) my-service。你希望用戶能夠用下面的 CLI 命令來生成它。

ng generate my-lib:my-service

首先,在 schematics 文件夾中新建一個子文件夾 my-service.

編輯一下 schematics/collection.json 文件,指向新的原理圖子文件夾,并附上一個指向模式文件的指針,該文件將會指定新原理圖的輸入。

進入 /schematics/my-service/ 目錄。

創(chuàng)建一個 schema.json 文件并定義該原理圖的可用選項。

每個選項都會把 key 與類型、描述和一個可選的別名關(guān)聯(lián)起來。該類型定義了你所期望的值的形態(tài),并在用戶請求你的原理圖給出用法幫助時顯示這份描述。

創(chuàng)建一個 schema.ts 文件,并定義一個接口,用于存放 schema.json 文件中定義的各個選項的值。

export interface Schema {// The name of the service.name: string;// The path to create the service.path?: string;// The name of the project.project?: string; }

name:你要為創(chuàng)建的這個服務(wù)指定的名稱。

path:覆蓋為原理圖提供的路徑。默認(rèn)情況下,路徑是基于當(dāng)前工作目錄的。

project:提供一個具體項目來運行原理圖。在原理圖中,如果用戶沒有給出該選項,你可以提供一個默認(rèn)值。

要把工件添加到項目中,你的原理圖就需要自己的模板文件。原理圖模板支持特殊的語法來執(zhí)行代碼和變量替換。

在 schematics/my-service/ 目錄下創(chuàng)建一個 files/ 文件夾。

創(chuàng)建一個名叫 name@dasherize.service.ts.template 的文件,它定義了一個可以用來生成文件的模板。這里的模板會生成一個已把 Angular 的 HttpClient 注入到其構(gòu)造函數(shù)中的服務(wù)。

文件內(nèi)容如下:

// #docregion template import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http';@Injectable({providedIn: 'root' }) export class <%= classify(name) %>Service {constructor(private http: HttpClient) { } }

classify 和 dasherize 方法是實用函數(shù),你的原理圖會用它們來轉(zhuǎn)換你的模板源碼和文件名。

name 是工廠函數(shù)提供的一個屬性。它與你在模式中定義的 name 是一樣的。

添加工廠函數(shù)

現(xiàn)在,你已經(jīng)有了基礎(chǔ)設(shè)施,可以開始定義一個 main 函數(shù)來執(zhí)行要對用戶項目做的各種修改了。

Schematics 框架提供了一個文件模板系統(tǒng),它支持路徑和內(nèi)容模板。系統(tǒng)會操作在這個輸入文件樹(Tree)中加載的文件內(nèi)或路徑中定義的占位符,用傳給 Rule 的值來填充它們。

關(guān)于這些數(shù)據(jù)結(jié)構(gòu)和語法的詳細(xì)信息,請參閱 Schematics 的 README。

創(chuàng)建主文件 index.ts 并為你的原理圖工廠函數(shù)添加源代碼。

首先,導(dǎo)入你需要的原理圖定義。Schematics 框架提供了許多實用函數(shù)來創(chuàng)建規(guī)則或在執(zhí)行原理圖時和使用規(guī)則。

代碼如下:

import {Rule, Tree, SchematicsException,apply, url, applyTemplates, move,chain, mergeWith } from '@angular-devkit/schematics';import { strings, normalize, virtualFs, workspaces } from '@angular-devkit/core';

導(dǎo)入已定義的模式接口,使用別名重定義為 MyServiceSchema,它會為你的原理圖選項提供類型信息。

要想構(gòu)建 “生成器原理圖”,我們從一個空白的規(guī)則工廠開始。

index.js 文件里:

export function myService(options: MyServiceSchema): Rule {return (tree: Tree) => {return tree;}; }

這個規(guī)則工廠返回樹而不做任何修改。這些選項都是從 ng generate 命令傳過來的選項值。

定義一個生成器規(guī)則

我們現(xiàn)在有了一個框架,可用來創(chuàng)建一些真正修改用戶程序的代碼,以便對庫中定義的服務(wù)進行設(shè)置。

用戶安裝過此庫的 Angular 工作區(qū)中會包含多個項目(應(yīng)用和庫)。用戶可以在命令行中指定一個項目,也可以使用它的默認(rèn)值。在任何一種情況下,你的代碼都需要知道應(yīng)該在哪個項目上應(yīng)用此原理圖,這樣才能從該項目的配置中檢索信息。

你可以使用傳給工廠函數(shù)的 Tree 對象來做到這一點。通過 Tree 的一些方法,你可以訪問此工作區(qū)的完整文件樹,以便在運行原理圖時讀寫文件。

獲取項目配置

要確定目標(biāo)項目,可以使用 workspaces.readWorkspace 方法在工作區(qū)的根目錄下讀取工作區(qū)配置文件 angular.json 的內(nèi)容。要想使用 workspaces.readWorkspace,你要先從這個 Tree 創(chuàng)建出一個 workspaces.WorkspaceHost。 將以下代碼添加到工廠函數(shù)中。

function createHost(tree: Tree): workspaces.WorkspaceHost {return {async readFile(path: string): Promise<string> {const data = tree.read(path);if (!data) {throw new SchematicsException('File not found.');}return virtualFs.fileBufferToString(data);},async writeFile(path: string, data: string): Promise<void> {return tree.overwrite(path, data);},async isDirectory(path: string): Promise<boolean> {return !tree.exists(path) && tree.getDir(path).subfiles.length > 0;},async isFile(path: string): Promise<boolean> {return tree.exists(path);},}; }export function myService(options: MyServiceSchema): Rule {return async (tree: Tree) => {const host = createHost(tree);const { workspace } = await workspaces.readWorkspace('/', host);}; }

workspaces 是從 @angular-devkit/core 導(dǎo)出的,readWorkspace 是其標(biāo)準(zhǔn)方法。該方法需要的第二個輸入?yún)?shù) host,是從另一個自定義函數(shù) createHost 返回的。

下面這行 default 邏輯處理:

if (!options.project) {options.project = workspace.extensions.defaultProject; }

此 workspace.extensions 屬性中包含一個 defaultProject 值,用來確定如果沒有提供該參數(shù),要使用哪個項目。如果 ng generate 命令中沒有明確指定任何項目,我們就會把它作為后備值。

有了項目名稱之后,用它來檢索指定項目的配置信息。

const project = workspace.projects.get(options.project); if (!project) {throw new SchematicsException(`Invalid project name: ${options.project}`); }const projectType = project.extensions.projectType === 'application' ? 'app' : 'lib';

options.path 決定了應(yīng)用原理圖之后,要把原理圖模板文件移動到的位置。
原理圖模式中的 path 選項默認(rèn)會替換為當(dāng)前工作目錄。如果未定義 path,就使用項目配置中的 sourceRoot 和 projectType 來確定。

邏輯體現(xiàn)在下面的代碼里:

if (options.path === undefined) {options.path = `${project.sourceRoot}/${projectType}`; }

sourceRoot 在 angular.json 里定義:

定義規(guī)則

Rule 可以使用外部模板文件,對它們進行轉(zhuǎn)換,并使用轉(zhuǎn)換后的模板返回另一個 Rule 對象。你可以使用模板來生成原理圖所需的任意自定義文件。

將以下代碼添加到工廠函數(shù)中。

const templateSource = apply(url('./files'), [applyTemplates({classify: strings.classify,dasherize: strings.dasherize,name: options.name}),move(normalize(options.path as string)) ]);

apply() 方法會把多個規(guī)則應(yīng)用到源碼中,并返回轉(zhuǎn)換后的源代碼。它需要兩個參數(shù),一個源代碼和一個規(guī)則數(shù)組。

url() 方法會從文件系統(tǒng)中相對于原理圖的路徑下讀取源文件。

applyTemplates() 方法會接收一個參數(shù),它的方法和屬性可用在原理圖模板和原理圖文件名上。它返回一條 Rule。你可以在這里定義 classify() 和 dasherize() 方法,以及 name 屬性。

classify() 方法接受一個值,并返回標(biāo)題格式(title case)的值。比如,如果提供的名字是 my service,它就會返回 MyService。Title case 和駝峰命名法類似,是一種變量拼寫規(guī)則。

dasherize() 方法接受一個值,并以中線分隔并小寫的形式返回值。比如,如果提供的名字是 MyService,它就會返回 “my-service” 的形式。

當(dāng)應(yīng)用了此原理圖之后,move 方法會把所提供的源文件移動到目的地。所以,my service 被轉(zhuǎn)換為 MyService,進而為 my-service.

規(guī)則工廠必須返回一條規(guī)則。

return chain([mergeWith(templateSource) ]);

該 chain() 方法允許你把多個規(guī)則組合到一個規(guī)則中,這樣就可以在一個原理圖中執(zhí)行多個操作。這里你只是把模板規(guī)則和原理圖要執(zhí)行的代碼合并在一起。

至此這個 Angular 庫的 Schematics 就開發(fā)完畢了,請持續(xù)關(guān)注 Jerry 后續(xù)文章,我會介紹如何消費這個 Schematics.

更多Jerry的原創(chuàng)文章,盡在:“汪子熙”:

總結(jié)

以上是生活随笔為你收集整理的Angular 原理图 Schematics 学习 - 动手开发一个实际的例子的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。