Angular使用cli生成自定义文件、组件

不得不说,和传统的复制黏贴来建立组件的方法相比,使用angular-cli的脚手架功能来建立模块、组件显得很是高效,不单单有了建立了文件,还包含了一些必须的代码,同时也将组件导入了最近的模块,一些重复性工做就使用cli能够节省掉。angular提供了丰富的文件类型,可是总归是有些咱们本身的项目须要,咱们须要建立自定义后缀的组件,这时候就不得不舍弃cli了,那么能不能使用自定义的方式来达到脚手架建立呢?css

angular 脚手架建立的方式

咱们首先来看看angular-cli提供的一些命令是怎么建立文件的。html

看angular文档咱们能够看到这个词:Schematic,这个词意为原理图。Schematic是一个脚手架库,定义如何经过建立、修改、重构或移动文件和代码来生成或转换编程项目。Angular Cli使用原理图生成和修改项目文件。库开发人员能够建立原理图,使Cli可以生成其已发布的库。能够查看https://www.npmjs.com/package/@angular-devkit/schematicsnode

那这样的话,咱们能够知道angular是借助的Schematic来生成项目文件。再查看发现node_module里面有个@Schematics/angular,里面定义了咱们可使用cli生成的全部文件,包括components\class\enum\interface等等。npm

点开查看components,里面有一些ts文件,还有一个files文件夹,里面包含着全部咱们生成component的文件:编程

  • __name@dasherize@if-flat__json

    • __name@dasherize__.component.__styleext__
    • __name@dasherize__.component.html
    • __name@dasherize__.component.spec.ts
    • __name@dasherize__.component.ts

那想一想,在咱们运行Cli建立组件的时候,会使用这里的模板,用file文件夹里面的文件生成项目组件。其余的先无论,咱们按照这里的components是否是能够来构造咱们本身的“原理图”呢?app

自定义原理图

先看看咱们的需求,咱们如今项目的项目里面,页面是page,按照angular原来的写法,全部的page的组件都是:XXXX.component.ts。咱们为了将页面和组件进行区分,页面的文件都是XXX.page.ts。咱们先在node_module/@Schematics/angula/下面复制component新建一个pageless

如今,将page下面的files文件夹中的文件名.component都改成.page(因为咱们不用单元测试文件,直接删除.spec.ts文件便可):单元测试

  • page测试

    • files

      • __name@dasherize@if-flat__

        • __name@dasherize__.page.__styleext__
        • __name@dasherize__.page.html
        • __name@dasherize__.page.ts
    • index.d.ts
    • index.js 命令运行时会执行这个js文件
    • schema.d.ts
    • schema.json 定义了这个生成器命令能够接受的参数

接下来再看page里面的index.js,这个js文件在咱们跑本身的命令的时候会执行。看这个文件,里面的代码虽然有点看不懂,可是猜猜仍是能够的,有些关键地方:

const componentPath = `/${options.path}/`
            + (options.flat ? '' : core_1.strings.dasherize(options.name) + '/')
            + core_1.strings.dasherize(options.name)
            + '.component';
const classifiedName = core_1.strings.classify(`${options.name}Component`);

相似于这样的地方,咱们发现就是建立对应的组件文件和里面的组件类。因此咱们把全部.component}Component的地方替换为.page}Page:

const componentPath = `/${options.path}/`
            + (options.flat ? '' : core_1.strings.dasherize(options.name) + '/')
            + core_1.strings.dasherize(options.name)
            + '.page';
const classifiedName = core_1.strings.classify(`${options.name}Page`);

而后接下来再看page/files/__name@dasherize__.page.ts

import { Component, OnInit<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
@Component({
  selector: '<%= selector %>',<% if(inlineTemplate) { %>
  template: `
    <p>
      <%= dasherize(name) %> works!
    </p>
  `,<% } else { %>
  templateUrl: './<%= dasherize(name) %>.component.html',<% } if(inlineStyle) { %>
  styles: []<% } else { %>
  styleUrls: ['./<%= dasherize(name) %>.component.<%= styleext %>']<% } %><% if(!!viewEncapsulation) { %>,
  encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
  changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
})
export class <%= classify(name) %>Component implements OnInit {
  constructor() { }
  ngOnInit() {
  }
}

这个是生成的组件的ts模板,咱们须要根据咱们的需求来改造,首先是文件里面的类,既然咱们如今的文件名是XXX.page.ts,那么里面的类也就须要时XXXPage形式的,而且咱们的页面是不容许做为指令的形式出现的,因此也要去掉selector元数据。那综合下来,咱们的__name@dasherize__.page.ts应该修改成:

import { Component, OnInit<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
@Component({
  templateUrl: './<%= dasherize(name) %>.page.html',
  <% if(inlineStyle) { %>
  styles: []<% } else { %>
  styleUrls: ['./<%= dasherize(name) %>.page.<%= styleext %>']<% } %><% if(!!viewEncapsulation) { %>,
  encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
  changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
})
export class <%= classify(name) %>Page implements OnInit {
  constructor() { }
  ngOnInit() {
  }
}

OK,目前为止,咱们的“原理图”就建立的差很少了,咱们如今须要加入cli指令上去。在@Schematics/angular/collection.json里面定义了cli的命令,一样,先观察componet的命令:

"component": {
    "aliases": [ "c" ], // 简写形式
    "factory": "./component", // 采用生成器
    "description": "Create an Angular component.",
    "schema": "./component/schema.json"
},

咱们来建立咱们本身的命令:

"component": {
    "aliases": [ "pa" ], // 简写形式
    "factory": "./page", // 采用生成器
    "description": "Create an Angular component page.",
    "schema": "./page/schema.json"
},

测试命令

目前为止,咱们已经添加好了咱们本身的生成命令,如今来尝试着生成一个page组件,在app/pages/user下面生成组件user-test,命令:ng g page pages/user/user-test,查看结果:

CREATE src/app/pages/user/user-test/user-test.page.css (0 bytes)
CREATE src/app/pages/user/user-test/user-test.page.html (28 bytes)
CREATE src/app/pages/user/user-test/user-test.page.ts (239 bytes)
UPDATE src/app/pages/user/user.module.ts (1803 bytes)

看看生成的ts文件:

import { Component, OnInit } from '@angular/core';
@Component({
  templateUrl: './user-test.page.html',
  styleUrls: ['./user-test.page.css']
})
export class UserTestPage implements OnInit {
  constructor() { }
  ngOnInit() {
  }
}

很是好啊,彻底知足咱们的需求。

慢着,我如今项目中使用的是less,并且使用component建立的组件里面的样式文件都是less,为啥咱们自定义的生成的是css文件???

极可能是没有识别咱们自定义的less,那咱们自定义的less是怎么定的呢?看看angular.json文件中有个project里面:

"schematics": {
    "@schematics/angular:component": {
        "styleext": "less"
    }
},

也就是说,咱们在这里配置了生成component组件时,styleextless,咱们的page命令是没有配置的,因此会找默认的样式文件后缀。那咱们在这里尝试加上试试看:

"schematics": {
    "@schematics/angular:component": {
        "styleext": "less"
    },
    "@schematics/angular:page": {
        "styleext": "less"
    }
},

再生成一下:

CREATE src/app/pages/user/user-test/user-test.page.less (0 bytes)
CREATE src/app/pages/user/user-test/user-test.page.html (28 bytes)
CREATE src/app/pages/user/user-test/user-test.page.ts (240 bytes)
UPDATE src/app/pages/user/user.module.ts (1804 bytes)

完美~

相关文章
相关标签/搜索