不得不說,和傳統的複製黏貼來建立組件的方法相比,使用angular-cli的腳手架功能來建立模塊、組件顯得很是高效,不單單有了建立了文件,還包含了一些必須的代碼,同時也將組件導入了最近的模塊,一些重複性工做就使用cli能夠節省掉。angular提供了豐富的文件類型,可是總歸是有些咱們本身的項目須要,咱們須要建立自定義後綴的組件,這時候就不得不捨棄cli了,那麼能不能使用自定義的方式來達到腳手架建立呢?css
咱們首先來看看angular-cli提供的一些命令是怎麼建立文件的。html
看angular文檔咱們能夠看到這個詞:Schematic
,這個詞意爲原理圖。Schematic
是一個腳手架庫,定義如何經過建立、修改、重構或移動文件和代碼來生成或轉換編程項目。Angular Cli使用原理圖生成和修改項目文件。庫開發人員能夠建立原理圖,使Cli可以生成其已發佈的庫。能夠查看https://www.npmjs.com/package/@angular-devkit/schematics。node
那這樣的話,咱們能夠知道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
新建一個page
。less
如今,將page下面的files文件夾中的文件名.component
都改成.page
(因爲咱們不用單元測試文件,直接刪除.spec.ts
文件便可):單元測試
page測試
files
__name@dasherize@if-flat__
__name@dasherize__.page.__styleext__
__name@dasherize__.page.html
__name@dasherize__.page.ts
接下來再看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
組件時,styleext
爲less
,咱們的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)
完美~