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 相关文章推荐
从零开始学习jQuery (六) jquery中的AJAX使用
Feb 23 Javascript
如何在一个页面显示多个百度地图
Apr 07 Javascript
AngularJS初始化过程分析(引导程序)
Dec 06 Javascript
jquery点击缩略图切换视频播放特效代码分享
Sep 15 Javascript
jQuery实现网页顶部固定导航效果代码
Dec 24 Javascript
Bootstrap媒体对象学习使用
Mar 07 Javascript
js,jq,css多方面实现简易下拉菜单功能
May 13 Javascript
关于Stream和Buffer的相互转换详解
Jul 26 Javascript
推荐VSCode 上特别好用的 Vue 插件之vetur
Sep 14 Javascript
JQuery扩展对象方法操作示例
Aug 21 jQuery
JavaScript数组特性与实践应用深入详解
Dec 30 Javascript
JavaScript实现抖音罗盘时钟
Oct 11 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性能的编码技巧以及性能优化详细解析
2013/08/24 PHP
php实现设计模式中的单例模式详解
2014/10/11 PHP
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
laravel框架如何设置公共头和公共尾
2019/10/22 PHP
Laravel 实现在Blade模版中使用全局变量代替路径的例子
2019/10/22 PHP
使用Modello编写JavaScript类
2006/12/22 Javascript
利用JQuery和JS实现奇偶行背景颜色自定义效果
2012/11/19 Javascript
封装的jquery翻页滚动(示例代码)
2013/11/18 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
2014/05/28 Javascript
jQuery中ajax和post处理json的不同示例对比
2014/11/02 Javascript
JavaScript兼容浏览器FF/IE技巧
2016/08/14 Javascript
BootStrap入门教程(一)之可视化布局
2016/09/19 Javascript
浅谈js中几种实用的跨域方法原理详解
2016/12/02 Javascript
深入理解Javascript中的观察者模式
2017/02/20 Javascript
React Native中TabBarIOS的简单使用方法示例
2017/10/13 Javascript
浅谈angularJS2中的界面跳转方法
2018/08/31 Javascript
JS设置自定义快捷键并实现图片上下左右移动
2019/10/17 Javascript
webpack3.0升级4.0的方法步骤
2020/04/02 Javascript
jQuery实现购物车全功能
2021/01/11 jQuery
[03:04]2018年国际邀请赛典藏宝瓶&莱恩声望物品展示 片尾有彩蛋
2018/06/04 DOTA
python基础教程之python消息摘要算法使用示例
2014/02/10 Python
python使用两种发邮件的方式smtp和outlook示例
2017/06/02 Python
初探利用Python进行图文识别(OCR)
2019/02/26 Python
python tkiner实现 一个小小的图片翻页功能的示例代码
2020/06/24 Python
pip install命令安装扩展库整理
2021/03/02 Python
viagogo英国票务平台:演唱会、体育比赛、戏剧门票
2017/03/24 全球购物
印度和世界各地的精美产品:Ikka Dukka
2018/02/12 全球购物
俄罗斯卫浴采暖及维修用品超级市场:Dkrussia
2020/05/12 全球购物
EMPHASIS艾斐诗官网:周生生旗下原创精品珠宝品牌
2020/12/17 全球购物
美容院考勤制度
2014/01/30 职场文书
酒店副总经理岗位职责范本
2014/02/04 职场文书
人事专员工作职责
2014/02/22 职场文书
技校毕业生自荐信
2014/06/03 职场文书
村党支部书记四风问题个人对照检查材料思想汇报
2014/10/06 职场文书
防灾减灾标语
2014/10/07 职场文书
MySQL数据库实验之 触发器和存储过程
2022/06/21 MySQL