代码生成工具Schematics详解(1)

2019-07-24  本文已影响0人  cocos2d

为什么要学习Schematics?

schematics作为Angular-Devkit的一部分,用过Angular CLI的人肯定用过这个命令 :

ng g component my-component

此命令瞬间创建了一个名为my-component的组件。如果使用了module参数,还会自动添加到模块的声明中。这样写代码确实爽,生产力成倍提高。

如何自己创建一个Schematic?

1.安装Schematics CLI

npm install -g @angular-devkit/schematics-cli
  1. 创建Schematics项目
    使用下面的命令新建一个 scheamtics 项目
$ schematics schematic --name my-schematics
$ cd my-schematics
$ npm install
  1. 编译和运行
    以上命令创建了一个简单的命令行Schematics,编译后就可以运行和调试了,可以先执行以下命令,来测试下效果
$ npm run build # 编译 ts
$ npm link      # link 当前项目

在你的Angular项目里执行以下命令:

$ ng new schematics-test # 新建一个 Angular 项目
$ cd my-angular-project    # 进入项目目录
$ npm link my-schematics # 将上一步的 schematics link 进来

之后,执行以下命令:

$ ng g my-schematics:my-full-schematic --name hello

其中my-schematics是包名,my-full-schematic是Schematic的名称。由于我们link了包名,所以ng可以找到自定义的Schematic。
会发现项目中多了几个文件:

   My Full Schematic: {"name":"hello","index":1}
            My Other Schematic: {"option":true}
                        My Schematic: {"option":true}
CREATE hola (5 bytes)
CREATE allo (5 bytes)
CREATE test2 (35 bytes)
CREATE test1 (18 bytes)
  1. 代码讲解
    从上面的执行结果可以看出:my-full-schematic调用了my-other-schematic,而my-other-schematic又调用了my-schematic。冒号后面的是参数。
"schematics": "./src/collection.json" 

指明了我们的Schematic的配置文件collection.json的位置

"schematics": {
    "my-schematic": {
      "description": "An example schematic",
      "factory": "./my-schematic/index#mySchematic"
    },
    "my-other-schematic": {
      "description": "A schematic that uses another schematics.",
      "factory": "./my-other-schematic"
    },
    "my-full-schematic": {
      "description": "A schematic using a source and a schema to validate options.",
      "factory": "./my-full-schematic",
      "schema": "./my-full-schematic/schema.json"
    }
  }

其中有三个Schematic,my-full-schematic有schema属性,指向一个配置文件schema.json,用来配置命令行的参数

{
  "$schema": "http://json-schema.org/schema",
  "id": "MyFullSchematicsSchema",
  "title": "My Full Schematics Schema",
  "type": "object",
  "properties": {
    "index": {
      "type": "number",
      "default": 1
    },
    "name": {
      "type": "string"
    }
  },
  "required": [
    "name"
  ]
}

properties属性定义了两个参数index和name,index有默认值1,name参数是必须的。还记得我们是怎么调用的吗?用户必须制定name参数,否则会有错误提示

$ ng g my-schematics:my-full-schematic --name hello
import {
  Rule,
  SchematicContext,
  Tree,
  apply,
  chain,
  mergeWith,
  schematic,
  template,
  url,
} from '@angular-devkit/schematics';

export default function (options: any): Rule {
  // chain是个特殊的rule,用来逐个调用rule传参
  return chain([
    (_tree: Tree, context: SchematicContext) => {
      // 打印此Schematic的参数
      context.logger.info('My Full Schematic: ' + JSON.stringify(options));
    },

    // 调用另一个schematic,并传参数
    schematic('my-other-schematic', { option: true }),

    // 合并树
    mergeWith(apply(url('./files'), [
      template({
        INDEX: options.index,
        name: options.name,
      }),
    ])),
  ]);
}

导出匿名函数,函数返回Rule。Rule是对Tree的操作,用于转换树。而Tree是真实文件目录的树形结构,以当前目录为根目录。
chain是一个特殊的Rule,用于顺序执行Rule数组。

Rule = (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | Promise<void> | Promise<Rule> | void;

Source = (context: SchematicContext) => Tree | Observable<Tree>;

根据上下文,返回Tree。

上一篇 下一篇

猜你喜欢

热点阅读