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 相关文章推荐
使用prototype.js进行异步操作
Feb 07 Javascript
兼容IE和Firefox的javascript获取iframe文档内容的函数
Aug 15 Javascript
关于scrollLeft,scrollTop的浏览器兼容性测试
Mar 19 Javascript
jquery弹出层类代码分享
Dec 27 Javascript
javascript实现修改微信分享的标题内容等
Dec 11 Javascript
Angular 中 select指令用法详解
Sep 29 Javascript
Jquery表单验证失败后不提交的解决方法
Oct 18 Javascript
BootstrapTable请求数据时设置超时(timeout)的方法
Jan 22 Javascript
js实现打地鼠小游戏
Feb 13 Javascript
浅谈Vue组件单元测试究竟测试什么
Feb 05 Javascript
Vue微信公众号网页分享的示例代码
May 28 Javascript
cypress测试本地web应用
Jun 01 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中用memcached实现页面防刷新功能
2014/08/19 PHP
JavaScript/jQuery 表单美化插件小结
2012/02/14 Javascript
JavaScript加强之自定义callback示例
2013/09/21 Javascript
如何正确使用Nodejs 的 c++ module 链接到 OpenSSL
2014/08/03 NodeJs
JavaScript link方法入门实例(给字符串加上超链接)
2014/10/17 Javascript
JavaScript的9种继承实现方式归纳
2015/05/18 Javascript
jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签
2016/03/29 Javascript
Angular 4依赖注入学习教程之ClassProvider的使用(三)
2017/06/04 Javascript
JS实现点击复选框变更DIV显示状态的示例代码
2017/12/18 Javascript
使用Node.js实现一个多人游戏服务器引擎
2019/03/13 Javascript
全面分析JavaScript 继承
2019/05/30 Javascript
JS获取动态添加元素的方法详解
2019/07/31 Javascript
Vue 解决多级动态面包屑导航的问题
2019/11/04 Javascript
[40:57]TI4 循环赛第二日 iG vs EG
2014/07/11 DOTA
python实现在无须过多援引的情况下创建字典的方法
2014/09/25 Python
详解Python中用于计算指数的exp()方法
2015/05/14 Python
使用Django的模版来配合字符串翻译工作
2015/07/27 Python
python开发之IDEL(Python GUI)的使用方法图文详解
2015/11/12 Python
分析Python中设计模式之Decorator装饰器模式的要点
2016/03/02 Python
Python 详解基本语法_函数_返回值
2017/01/22 Python
Python爬取数据并写入MySQL数据库的实例
2018/06/21 Python
Python 中包/模块的 `import` 操作代码
2019/04/22 Python
基于Python实现扑克牌面试题
2019/12/11 Python
Python+Selenium实现自动化的环境搭建的步骤(图文)
2020/09/01 Python
GoDaddy英国:全球排名第一的域名注册商
2018/06/08 全球购物
C#面试常见问题
2013/02/25 面试题
如何手工释放资源
2013/12/15 面试题
授权委托书样本
2014/09/25 职场文书
群众路线自我剖析范文
2014/11/04 职场文书
班主任自我评价范文
2015/03/11 职场文书
电子商务专业求职信范文
2015/03/19 职场文书
运动员入场词
2015/07/18 职场文书
工作感言一句话
2015/08/01 职场文书
CSS3 制作的悬停缩放特效
2021/04/13 HTML / CSS
7个你应该知道的JS原生错误类型
2021/04/29 Javascript
mybatis 获取更新记录的id
2022/05/20 Java/Android