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 相关文章推荐
用 javascript 实现的点击复制代码
Mar 24 Javascript
JavaScript CSS 修改学习第四章 透明度设置
Feb 19 Javascript
java与javascript之间json格式数据互转介绍
Oct 29 Javascript
jQuery插件MixItUp实现动画过滤和排序
Apr 12 Javascript
js实现的黑背景灰色二级导航菜单效果代码
Aug 24 Javascript
javascript实现tab切换特效
Nov 12 Javascript
js判断请求的url是否可访问,支持跨域判断的实现方法
Sep 17 Javascript
Angular 中 select指令用法详解
Sep 29 Javascript
jQuery 获取select选中值及清除选中状态
Dec 13 Javascript
vue.js移动端tab组件的封装实践实例
Jun 30 Javascript
JavaScript实现的浏览器下载文件的方法
Aug 09 Javascript
详解如何在vue项目中使用lodop打印插件
Sep 27 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 字符串 小常识
2009/06/05 PHP
PHP 输出简单动态WAP页面
2009/06/09 PHP
PHP数组 为文章加关键字连接 文章内容自动加链接
2011/12/29 PHP
PHP可变函数学习小结
2015/11/29 PHP
PHP二进制与字符串之间的相互转换教程
2016/10/14 PHP
Swoole实现异步投递task任务案例详解
2019/04/02 PHP
laravel 多图上传及图片的存储例子
2019/10/14 PHP
JavaScript 的方法重载效果
2009/08/07 Javascript
Jquery封装tab自动切换效果的具体实现
2013/07/13 Javascript
JS检测图片大小的实例
2013/08/21 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
javascript制作网页图片上实现下雨效果
2015/02/26 Javascript
AngularJS基础 ng-keypress 指令简单示例
2016/08/02 Javascript
jQuery双向列表选择器DIV模拟版
2016/11/01 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
扩展bootstrap的modal模态框-动态添加modal框-弹出多个modal框
2017/02/21 Javascript
js css3实现图片拖拽效果
2017/03/04 Javascript
input输入框内容实时监测(附代码)
2017/08/15 Javascript
JavaScript深拷贝和浅拷贝概念与用法实例分析
2018/06/07 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
2018/08/10 Javascript
Nuxt pages下不同的页面对应layout下的页面布局操作
2020/11/05 Javascript
[02:09]2018DOTA2亚洲邀请赛TNC赛前采访
2018/04/04 DOTA
探究数组排序提升Python程序的循环的运行效率的原因
2015/04/01 Python
Python实现抢购IPhone手机
2018/02/07 Python
解决pip install的时候报错timed out的问题
2018/06/12 Python
Python OpenCV读取png图像转成jpg图像存储的方法
2018/10/28 Python
Python发送邮件测试报告操作实例详解
2018/12/08 Python
Python程序包的构建和发布过程示例详解
2019/06/09 Python
Python操作redis和mongoDB的方法
2019/12/19 Python
欧洲最大的化妆品连锁公司:Douglas道格拉斯
2017/05/06 全球购物
大学生职业生涯规划书模板
2014/01/03 职场文书
职工运动会邀请函
2014/01/19 职场文书
工作鉴定评语
2014/05/04 职场文书
实习介绍信模板
2015/01/30 职场文书
Redis高并发防止秒杀超卖实战源码解决方案
2021/11/01 Redis
Pytorch中expand()的使用(扩展某个维度)
2022/07/15 Python