准备
- 全局安装
@angular-devkit/schematics-cli
以使用schematics
命令
$ npm install -g @angular-devkit/schematics-cli
- 创建新的
Schematics
项目
$ schematics blank <schematic-name>
在已生成的Schematics工程根目录下调用该命令会快速添加一个以填写的<schematic-name>
命名的schematic空白模板,并在collection.json
中添加相应基础信息。
步骤
创建一个Schematics初始工程
$ schematics blank my-schematics
$ cd my-schematics
$ npm i
1. Schematics文件构成
/src/collection.json
collection.json
文件是整个Schematics的主要定义文件,并且包含该库中所有可用schematic模板的定义。
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-schematics": {
"description": "A blank schematic.",
"factory": "./my-schematics/index#mySchematics"
}
}
}
description
:描述该Schematic模板factory
:指明该Schematic模板入口。从该文件可以看出,生成的Schematics初始工程默认提供了一个同名的my-schematics
模板,指向./my-schematics/index
文件并特别指向mySchematics
函数。也可以仅使用"factory": "./my-schematics/index"
, 需要将index.ts
中export function mySchematics(){}
更改为export default function(){}
。
附加属性:
aliases
(可选):指定该Schematic模板的一个或多个别名,以string数组表示。schema
(可选):指明每个Schematic模板单独的schema和所有的可用的命令行选项参数。
另外,注意Schematics工程中package.json
有一个schematic
属性指向 collection.json
文件。
index.ts
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
// 可以不用将本函数设置为默认导出,同一文件中可以有多个 rule factory
// 这是一个 schematic 工厂函数,最终返回一个 rule
export function mySchematics(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
// schematic rule 会被 Tree 和 Schematic context 调用
// rule 会把对文件的变换处理添加到 Tree 上,返回处理后的 Tree 给下一条 rule,这就是说,schematic rule 是可组合的
return tree;
};
}
schema.json
(需要时手动创建)
{
"$schema": "http://json-schema.org/schema",
"$id": "MyFirstSchematic",
"title": "Hello Option Schema",
"type": "object",
"description": "My First Schematic",
"properties": {
"name": { // 参数名
"type": "string", // 参数类型
"description": "The name of file", // 参数描述
"$default": { // 设为默认参数
"$source": "argv", // 从命令行命令传入
"index": 0 // 在命令中的默认位置。
// 例如:schematics .:my-schematics Mirai (默认位置)
// 对比 schematics .:my-schematics --name=Mirai (标准传入形式)
},
"x-prompt": "Who do we want to greet?" // 未传入该位置参数时的交互提示
}
},
"required": [
"name"
]
}
2. Schematics 相关基本概念
factory
工厂函数将接受一些自定义的参数 _options
并返回一条规则。
Rule
规则是通过Tree和SchematicContext调用的,并且可以调用其他已经实现的规则。一旦被调用,规则将对树进行调整,并将其返回以供进一步处理。
Tree
Tree 是工作空间中每个文件的虚拟表示。使用虚拟树而不是直接操作文件有以下一些优势:1)只有在每个 schematic 都成功运行的情况下,我们才会提交对树的更改。 2)在 debug 模式下(使用 --dry-run
标识),可以预览文件的改动而不影响实际的文件系统。 3)I/O 操作仅发生在整个处理过程结束后。
3. 从一个简单的例子体验Schematics
让我们从默认生成的 /src/my-schematics
模板开始体验。
//index.ts
export function mySchematics(_options: any): Rule {
return (tree: Tree, _context: SchematicContext) => {
tree.create('hello.js', `console.log('Hello Schematics');`);
return tree;
};
}
构建并在当前工程根目录下运行:
$ npm run build
$ schematics .:my-schematics
运行结果:显示 CREATE hello.js (32 bytes)
但没有实际文件生成。
原因:在使用相对路径调用schematics时默认为调试模式,每次使用时需要添加 --debug=false
或 --dry-run=false
关闭调试模式。
再次调用 schematics .:my-schematics --debug=false
,至此,成功生成一个 hello.js
文件,其内容为 console.log('Hello Schematics');
。
4. 向schematics传入自定义选项
在/src/my-schematics
下创建schema.json
,添加以下代码。这里我们以自定义一个name
参数为例。
{
"$schema": "http://json-schema.org/schema",
"$id": "MyFirstSchematic",
"title": "Hello Option Schema",
"type": "object",
"description": "My First Schematic",
"properties": {
"name": {
"type": "string",
"description": "The name of file",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Who do we want to greet?"
}
},
"required": [
"name"
]
}
在 collection.json
中引入创建的 schema.json
。
{
"$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"my-schematics": {
"description": "A blank schematic.",
"factory": "./my-schematics/index#mySchematics",
"schema": "./my-schematics/schema.json" // add this
}
}
}
同时,也可以创建一个 schema.d.ts
来为我们的原理图提供代码及类型的检查。
export interface Schema{
name: string;
}
随后于 index.ts
中引入并使用定义的Schema
类型(function mySchematics(_options: Schema): Rule
)。
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { Schema } from './schema';
export function mySchematics(_options: Schema): Rule {
return (tree: Tree, _context: SchematicContext) => {
const { name } = _options;
tree.create('hello.js', `console.log('Hello ${name}');`);
return tree;
};
}
调试(每次调试前将上次生成的hello.js
删除):
$ npm run build
$ schematics .:my-schematics Mirai --debug=false
or
$ schematics .:my-schematics --name=Mirai --debug=false
or
$ schematics .:my-schematics --debug=false
未传入name参数会提示: ? Who do we want to greet?
显示生成hello.js
文件(CREATE hello.js (27 bytes)
),内容:console.log('Hello Mirai');
,参数传入成功!
5. 生成更复杂的schematic模板
创建一个新的模板component
来体验类似ng g c <component-name>
命令生成的<component-name>.component.ts
文件。
在根目录下调用schematics blank component
,在生成/src/component/
文件夹下创建files
文件夹,并在里面创建__name@dasherize__.component.ts.template
文件。(另外需要在/src/component/
文件夹下创建schema.json
schema.d.ts
,在collection.json
中添加schema
属性等,见上一步)
// __name@dasherize__.component.ts.template
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-<%= dasherize(name) %>',
templateUrl: './<%= dasherize(name) %>.component.html',
styleUrls: ['./<%= dasherize(name) %>.component.css']
})
export class <%= classify(name) %>Component implements OnInit {
constructor() { }
ngOnInit() {
}
}
模板文件书写:
- 模板语言使用 EJS
- 从
@angular-devkit/core
中引入strings
,使用其中的dasherize / classify / underscore
等方法对name
进行处理。
EJS标签含义:
- <% '脚本' 标签,用于流程控制,无输出。
- <%_ 删除其前面的空格符
- <%= 输出数据到模板(输出是转义 HTML 标签)
- <%- 输出非转义的数据到模板
- <%# 注释标签,不执行、不输出内容
- <%% 输出字符串 '<%'
- %> 一般结束标签
- -%> 删除紧随其后的换行符
- _%> 将结束标签后面的空格符删除
// index.ts
import { Rule, SchematicContext, Tree, mergeWith, applyTemplates, apply, url } from '@angular-devkit/schematics';
import { Schema } from './schema';
import { strings } from '@angular-devkit/core';
export function component(_options: Schema): Rule {
return (tree: Tree, _context: SchematicContext) => {
return mergeWith(apply(url('./files'), [
applyTemplates({
...strings,
name: _options.name
})
]))(tree, _context); //(tree, _context)防止TS编译器报警 "tree 未使用"
};
}
修改index.ts
中的转换规则:
url()
指定模板文件路径。applyTemplate()
接受向模板文件嵌入的参数及处理函数,转换文件同时删去.template
后缀。apply()
对模板源应用多个规则,并返回转换后的模板。- 从
@angular-devkit/schematics
中引入以上方法。
在当前工程根路径下执行:
$ npm run build
$ schematics .:component --name=UserList --debug=false
成功生成user-list.component
文件,可以看到,内容中name
参数被修改为传入的UserList
的对应格式。
最后发布至NPM,就可以在项目中快速生成自定义的模板代码啦。
总结
以上是一个基本的模板生成例子,Schematics
运行在一个 Node 容器内,所以其可玩性非常强,可以操作文件并修改文件内容,绝大多数文件类型都可以找到相对应的现有类库来支持。
参考@schematics/angular
包,可以封装一些类似其utility
下的公用方法,来指定生成文件的路径或验证所填参数等。
参考
Total Guide To Custom Angular Schematics
Schematicsを作ってみよう
angular-cli/packages/angular_devkit/schematics
Use Angular Schematics to Simplify Your Life
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!