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


Posted in Javascript onSeptember 04, 2018

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

angular 脚手架创建的方式

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

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

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

点开查看components,里面有一些ts文件,还有一个files文件夹,里面包含着所有我们生成component的文件:

__name@dasherize@if-flat__

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

那想想,在我们运行Cli创建组件的时候,会使用这里的模板,用file文件夹里面的文件生成项目组件。其他的先不管,我们按照这里的components是不是可以来构造我们自己的“原理图”呢?

自定义原理图

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

现在,将page下面的files文件夹中的文件名.component都改为.page(由于我们不用单元测试文件,直接删除.spec.ts文件即可):

page

  1. files
    1. __name@dasherize@if-flat__
    2. __name@dasherize__.page.__styleext__
    3. __name@dasherize__.page.html
    4. __name@dasherize__.page.ts
  2. index.d.ts
  3. index.js 命令运行时会执行这个js文件
  4. schema.d.ts
  5. 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组件时,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)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
浅析JS刷新框架中的其他页面 &amp;&amp; JS刷新窗口方法汇总
Jul 08 Javascript
22点关于jquery性能优化的建议
May 28 Javascript
js漂浮广告实现代码
Aug 15 Javascript
jQuery实现可高亮显示的二级CSS菜单效果
Sep 01 Javascript
Javascript中神奇的this
Jan 20 Javascript
BootStrap Table 分页后重新搜索问题的解决办法
Aug 08 Javascript
jQuery手指滑动轮播效果
Dec 22 Javascript
ES6实现的遍历目录函数示例
Apr 07 Javascript
Vue和Bootstrap的整合思路详解
Jun 30 Javascript
深入浅析Vue中的Prop
Jun 10 Javascript
js实现简单分页导航栏效果
Jun 28 Javascript
Node.js从字符串生成文件流的实现方法
Aug 18 Javascript
vue2.0 使用element-ui里的upload组件实现图片预览效果方法
Sep 04 #Javascript
使用elementUI实现将图片上传到本地的示例
Sep 04 #Javascript
element UI upload组件上传附件格式限制方法
Sep 04 #Javascript
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
Sep 04 #Javascript
webpack 3.X学习之多页面打包的方法
Sep 04 #Javascript
JS获取并处理php数组的方法实例分析
Sep 04 #Javascript
vue click.stop阻止点击事件继续传播的方法
Sep 04 #Javascript
You might like
PHP中使用数组实现堆栈数据结构的代码
2012/02/05 PHP
php中用socket模拟http中post或者get提交数据的示例代码
2013/08/08 PHP
php目录拷贝实现方法
2015/07/10 PHP
PHP设计模式之简单投诉页面实例
2016/02/24 PHP
基于php双引号中访问数组元素报错的解决方法
2018/02/01 PHP
php创建多级目录与级联删除文件的方法示例
2019/09/12 PHP
ExtJs默认的字体大小改变的几种方法(自己整理)
2013/04/18 Javascript
如何将php数组或者对象传递给javascript
2014/03/20 Javascript
JS 新增Cookie 取cookie值 删除cookie 举例详解
2014/10/10 Javascript
jquery获取checkbox的值并post提交
2015/01/14 Javascript
浅谈javascript中this在事件中的应用
2015/02/15 Javascript
jQuery checkbox选中问题之prop与attr注意点分析
2016/11/15 Javascript
angularJS深拷贝详解
2017/03/23 Javascript
利用vue开发一个所谓的数独方法实例
2017/12/21 Javascript
Node.js文件编码格式的转换的方法
2018/04/27 Javascript
vue-cli 打包后提交到线上出现 &quot;Uncaught SyntaxError:Unexpected token&quot; 报错
2018/11/06 Javascript
VUE 解决mode为history页面为空白的问题
2019/11/01 Javascript
详解vue父子组件状态同步的最佳方式
2020/09/10 Javascript
[01:24:16]2018DOTA2亚洲邀请赛 4.6 全明星赛
2018/04/10 DOTA
python使用pyhook监控键盘并实现切换歌曲的功能
2014/07/18 Python
Python3 正在毁灭 Python的原因分析
2014/11/28 Python
编写同时兼容Python2.x与Python3.x版本的代码的几个示例
2015/03/30 Python
python pandas库中DataFrame对行和列的操作实例讲解
2018/06/09 Python
python高级特性和高阶函数及使用详解
2018/10/17 Python
Python之lambda匿名函数及map和filter的用法
2019/03/05 Python
python实现登录密码重置简易操作代码
2019/08/14 Python
Python3和pyqt5实现控件数据动态显示方式
2019/12/13 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
详解HTML5通讯录获取指定多个人的信息
2016/12/20 HTML / CSS
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
瑞士灯具购物网站:Lampenwelt.ch
2018/07/08 全球购物
大学生最常用的自我评价
2013/12/07 职场文书
拾金不昧表扬信范文
2014/01/11 职场文书
办公室主任个人总结
2015/02/28 职场文书
大学生党课感想
2015/08/11 职场文书
iOS 16进一步确认,一共支持16款iPhone
2022/04/28 数码科技