美文网首页
代码生成工具Schematics详解(1)

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

作者: cocos2d | 来源:发表于2019-07-24 19:30 被阅读0次

    为什么要学习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。冒号后面的是参数。
    • package.json
    "schematics": "./src/collection.json" 
    

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

    • 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.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
    
    • my-full-schematic/index.ts
    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的定义
    Rule = (tree: Tree, context: SchematicContext) => Tree | Observable<Tree> | Rule | Promise<void> | Promise<Rule> | void;
    
    
    • schematic
      用与调用其他schematic的Rule
    • mergeWith
      合并树到输入树中。假想有一个文件树,base目录是当前目录,也就是你执行ng命令的目录,这个树作为输入树input tree,输入给schematic的工作流中。schematic就像一个转换器,可以在这棵树上创建文件,或者修改现有文件等。最后,Schematic根据此Tree生成代码到我们的项目中。mergeWith就是合并Source到这棵树中。
    • Source
    Source = (context: SchematicContext) => Tree | Observable<Tree>;
    

    根据上下文,返回Tree。

    • apply
      应用Rule到Source后,返回新的Source
    • template
      类似于模板引擎ejs
    • url
      返回某一路径下的Source
      这些函数都是angular-dev下的,可以直接使用。如深究,建议阅读Schematics的源代码

    相关文章

      网友评论

          本文标题:代码生成工具Schematics详解(1)

          本文链接:https://www.haomeiwen.com/subject/zeaulctx.html