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)

完美~

相關文章
相關標籤/搜索