smart_dream

smart_dream 查看完整档案

重庆编辑重庆文理学院  |  信息与计算科学 编辑  |  填写所在公司/组织填写个人主网站
编辑

在学习前端的道路上不断提升自己

个人动态

smart_dream 发布了文章 · 2020-08-14

空白电脑安装前端软件

webstrom下载地址:https://www.jetbrains.com/webstorm/download/other.html

SublimeText3:http://www.sublimetext.com/3

Git下载地址:https://git-scm.com/

node(npm是包含在node.js里面的一个包管理工具):http://nodejs.cn/download/   

Chrome浏览器:https://www.google.cn/intl/zh-CN/chrome/

Notepad++是在微软视窗环境之下的一个免费的代码编辑器:https://www.notepad-plus-plus.org/downloads/

Adobe Systems旗下的:Photoshop(图像编辑);Illustrator(矢量图编辑);Dreamweaver(页面编辑-个人认为只适合初学者)

查看原文

赞 0 收藏 0 评论 0

smart_dream 关注了专栏 · 2018-10-24

张旭超-web前端开发工程师

爱运动的程序员

关注 57

smart_dream 收藏了文章 · 2018-10-19

RxJS: 简单入门

Introduction to RxJS

1. 前言

1.1 什么是RxJS

RxJSReactiveX编程理念的JavaScript版本。ReactiveX来自微软,它是一种针对异步数据流的编程。简单来说,它将一切数据,包括HTTP请求,DOM事件或者普通数据等包装成流的形式,然后用强大丰富的操作符对流进行处理,使你能以同步编程的方式处理异步数据,并组合不同的操作符来轻松优雅的实现你所需要的功能。

1.2 RxJS可用于生产吗?

ReactiveX由微软于2012年开源,目前各语言库由ReactiveX组织维护。RxJSGitHub上已有8782个star,目前最新版本为5.5.2,并持续开发维护中,其中官方测试用例共计2699个。

谁在使用Rx

1.3 RxJS对项目代码的影响?

RxJS中的流以Observable对象呈现,获取数据需要订阅Observable,形式如下:

const ob = http$.getSomeList(); //getSomeList()返回某个由`Observable`包装后的http请求
ob.subscribe((data) => console.log(data));
//在变量末尾加$表示Observable类型的对象。

以上与Promise类似:

const promise = http.getSomeList(); // 返回由`Promise`包装的http请求
promise.then((data) => console.log(data));

实际上Observable可以认为是加强版的Promise,它们之间是可以通过RxJSAPI互相转换的:

const ob = Observable.fromPromise(somePromise); // Promise转为Observable
const promise = someObservable.toPromise(); // Observable转为Promise

因此可以在Promise方案的项目中安全使用RxJS,并能够随时升级到完整的RxJS方案。

1.4 RxJS会增加多少体积?

RxJS(v5)整个库压缩后约为140KB,由于其模块化可扩展的设计,因此仅需导入所用到的类与操作符即可。导入RxJS常用类与操作符后,打包后的体积约增加30-60KB,具体取决于导入的数量。

不要用 import { Observable } from 'rxjs'这种方式导入,这会导入整个rxjs库,按需导入的方式如下:
import { Observable } from 'rxjs/Observable' //导入类
import 'rxjs/add/operator/map' // 导入实例操作符
import 'rxjs/add/observable/forkJoin' // 导入类操作符

2. RxJS快速入门

2.1 初级核心概念

  • Observable
  • Observer
  • Operator

Observable被称为可观察序列,简单来说数据就在Observable中流动,你可以使用各种operator对流进行处理,例如:

const ob = Observable.interval(1000);
ob.take(3).map(n => n * 2).filter(n => n > 2);

第一步代码我们通过类方法interval创建了一个Observable序列,ob作为源会每隔1000ms发射一个递增的数据,即0 -> 1 -> 2。第二步我们使用操作符对流进行处理,take(3)表示只取源发射的前3个数据,取完第三个后关闭源的发射;map表示将流中的数据进行映射处理,这里我们将数据翻倍;filter表示过滤掉出符合条件的数据,根据上一步map的结果,只有第二和第三个数据会留下来。

上面我们已经使用同步编程创建好了一个流的处理过程,但此时ob作为源并不会立刻发射数据,如果我们在map中打印n是不会得到任何输出的,因为ob作为Observable序列必须被“订阅”才能够触发上述过程,也就是subscribe(发布/订阅模式)。

const ob = Observable.interval(1000);
ob.take(3).map(n => n * 2).filter(n => n > 0).subscribe(n => console.log(n));

结果:

2 //第2秒
4 //第3秒

上面代码中我们给subscribe传入了一个函数,这其实是一种简写,subscribe完整的函数签名如下:

ob.subscribe({
    next: d => console.log(d),
    error: err => console.error(err),
    complete: () => console.log('end of the stream')
})

直接给subscribe传入一个函数会被当做是next函数。这个完整的包含3个函数的对象被称为observer(观察者),表示的是对序列结果的处理方式。next表示数据正常流动,没有出现异常;error表示流中出错,可能是运行出错,http报错等等;complete表示流结束,不再发射新的数据。在一个流的生命周期中,errorcomplete只会触发其中一个,可以有多个next(表示多次发射数据),直到complete或者error

observer.next可以认为是Promisethen的第一个参数,observer.error对应第二个参数或者Promisecatch

RxJS同样提供了catch操作符,err流入catch后,catch必须返回一个新的Observable。被catch后的错误流将不会进入observererror函数,除非其返回的新observable出错。

Observable.of(1).map(n => n.undefinedMethod()).catch(err => {
    // 此处处理catch之前发生的错误
    return Observable.of(0); // 返回一个新的序列,该序列成为新的流。
});

2.2 创建可观察序列

创建一个序列有很多种方式,我们仅列举常用的几种:

Observable.of(...args)

Observable.of()可以将普通JavaScript数据转为可观察序列,点我测试

Observable.fromPromise(promise)

Promise转化为Observable点我测试

Observable.fromEvent(elment, eventName)

DOM事件创建序列,例如Observable.fromEvent($input, 'click')点我测试

Observable.ajax(url | AjaxRequest)

发送http请求,AjaxRequest参考这里

Observable.create(subscribe)

这个属于万能的创建方法,一般用于只提供了回调函数的某些功能或者库,在你用这个方法之前先想想能不能用RxJS上的类方法来创建你所需要的序列,点我测试

2.3 合并序列

合并序列也属于创建序列的一种,例如有这样的需求:进入某个页面后拿到了一个列表,然后需要对列表每一项发出一个http请求来获取对应的详细信息,这里我们把每个http请求作为一个序列,然后我们希望合并它们。
合并有很多种方式,例如N个请求按顺序串行发出(前一个结束再发下一个);N个请求同时发出并且要求全部到达后合并为数组,触发一次回调;N个请求同时发出,对于每一个到达就触发一次回调。
如果不用RxJS,我们会比较难处理这么多情形,不仅实现麻烦,维护更麻烦,下面是使用RxJS对上述需求的解决方案:

const ob1 = Observable.ajax('api/detail/1');
const ob2 = Observable.ajax('api/detail/2');
...
const obs = [ob1, ob2...];
// 分别创建对应的HTTP请求。
  1. N个请求按顺序串行发出(前一个结束再发下一个)
Observable.concat(...obs).subscribe(detail => console.log('每个请求都触发回调'));
  1. N个请求同时并行发出,对于每一个到达就触发一次回调
Observable.merge(...obs).subscribe(detail => console.log('每个请求都触发回调'));
  1. N个请求同时发出并且要求全部到达后合并为数组,触发一次回调
Observable.forkJoin(...obs).subscribe(detailArray => console.log('触发一次回调'));

3. 使用RxJS实现搜索功能

搜索是前端开发中很常见的功能,一般是监听<input />keyup事件,然后将内容发送到后台,并展示后台返回的数据。

<input id="text"></input>
<script>
    var text = document.querySelector('#text');
    text.addEventListener('keyup', (e) =>{
        var searchText = e.target.value;
        // 发送输入内容到后台
        $.ajax({
            url: `/search/${searchText}`,
            success: data => {
              // 拿到后台返回数据,并展示搜索结果
              render(data);
            }
        });
    });
</script>

上面代码实现我们要的功能,但存在两个较大的问题:

  • 多余的请求

当想搜索“爱迪生”时,输入框可能会存在三种情况,“爱”、“爱迪”、“爱迪生”。而这三种情况将会发起 3 次请求,存在 2 次多余的请求。

  • 已无用的请求仍然执行

一开始搜了“爱迪生”,然后马上改搜索“达尔文”。结果后台返回了“爱迪生”的搜索结果,执行渲染逻辑后结果框展示了“爱迪生”的结果,而不是当前正在搜索的“达尔文”,这是不正确的。

减少多余请求数,可以用 setTimeout 函数节流的方式来处理,核心代码如下:

<input id="text"></input>
<script>
    var text = document.querySelector('#text'),
        timer = null;
    text.addEventListener('keyup', (e) =>{
        // 在 250 毫秒内进行其他输入,则清除上一个定时器
        clearTimeout(timer);
        // 定时器,在 250 毫秒后触发
        timer = setTimeout(() => {
            console.log('发起请求..');
        },250)
    })
</script>

已无用的请求仍然执行 的解决方式,可以在发起请求前声明一个当前搜索的状态变量,后台将搜索的内容及结果一起返回,前端判断返回数据与当前搜索是否一致,一致才走到渲染逻辑。最终代码为:

<input id="text"></input>
<script>
    var text = document.querySelector('#text'),
        timer = null,
        currentSearch = '';

    text.addEventListener('keyup', (e) =>{
        clearTimeout(timer)
        timer = setTimeout(() => {
            // 声明一个当前所搜的状态变量
            currentSearch = '书'; 

            var searchText = e.target.value;
            $.ajax({
                url: `/search/${searchText}`,
                success: data => {
                    // 判断后台返回的标志与我们存的当前搜索变量是否一致
                    if (data.search === currentSearch) {
                        // 渲染展示
                        render(data);
                    } else {
                        // ..
                    }
                }           
            });
        },250)
    })
</script>

上面代码基本满足需求,但代码开始显得乱糟糟。我们来使用RxJS实现上面代码功能,如下:

var text = document.querySelector('#text');
var inputStream = Rx.Observable.fromEvent(text, 'keyup') //为dom元素绑定'keyup'事件
                    .debounceTime(250) // 防抖动
                    .pluck('target', 'value') // 取值
                    .switchMap(url => Http.get(url)) // 将当前输入流替换为http请求
                    .subscribe(data => render(data)); // 接收数据

RxJS能简化你的代码,它将与流有关的内部状态封装在流中,而不需要在流外定义各种变量来以一种上帝视角控制流程。Rx的编程方式使你的业务逻辑流程清晰,易维护,并显著减少出bug的概率。

个人总结的常用操作符:

类操作符(通常为合并序列或从已有数据创建序列)
合并forkJoin, merge, concat
创建of, from, fromPromise, fromEvent, ajax, throw
实例操作符(对流中的数据进行处理或者控制流程)
map, filter,switchMap, toPromise, catch, take, takeUntil, timeout, debounceTime, distinctUntilChanged, pluck
对于这些操作符的使用不再详细描述,请参阅网上资料。

中文官网 http://cn.rx.js.org/
附上个人翻译的一些文章

最后打个广告,蚂蚁金服大安全风控+团队招人,前端后台都要,简历发送至huitong.zht@antfin.com。

参考文章:构建流式应用:RxJS 详解

查看原文

smart_dream 赞了回答 · 2018-10-17

解决webstorm打开typescript代码部分字体不显示高亮,黑色导致看不见

Preferences -> Editor -> Colors & Fonts -> Typescript

试着调整一下这个颜色试试?

如果调整这里不行,那有可能是没有解析成功,然后使用的是 Error(Not Found)的颜色设置。不过 Error 状态的默认颜色设置也不是这样的

刚试了下,只要调那个 Interface 的颜色就可以了。如果你选了 Use inherited attributes(默认是选中的),要先把那个勾去掉才行。或者你可以点一下 Language Default 看看那是什么颜色。

clipboard.png

调整后,这些颜色都会改:

clipboard.png

关注 2 回答 1

smart_dream 收藏了文章 · 2018-10-15

Angular CLI 终极指南

阅读 Angular 6/RxJS 最新教程,请访问前端修仙之路

Angular CLI 是什么?

Angular CLI 是一个命令行接口(Command Line Interface),用于实现自动化开发工作流程。它允许你做以下这些事情:

  • 创建一个新的 Angular 应用程序
  • 运行带有 LiveReload 支持的开发服务器,以便在开发过程中预览应用程序
  • 添加功能到现有的 Angular 应用程序
  • 运行应用程序的单元测试
  • 运行应用程序的端到端 (E2E) 测试
  • 构建应用程序

在详细介绍 Angular CLI 之前,我们先来看一下如何安装 Angular CLI

前提条件

在使用 Angular CLI 之前,你必须确保系统中 Node.js 的版本高于 6.9.0 且 npm 的版本高于 3.0.0

若你尚未安装 Node.js,你可以访问 Node.js 官网,然后根据你所用的操作系统选择对应的安装方式。

若你本机已经安装 Node.js 和 npm,你可以通过运行以下命令,确认一下当前环境信息:

$ node - v # 显示当前Node.js的版本
$ npm -v # 显示当前npm的版本

当你本机 Node.js 环境确认无误后,你可以在命令行使用 npm 安装 TypeScript

$ npm install -g typescript # 安装最新的TypeScript稳定版

安装 Angular CLI

若要安装 Angular CLI,只需在命令行中运行以下命令:

$ npm install -g @angular/cli

验证是否成功安装 Angular CLI,可在命令行运行:

$ ng version

在我本机运行上述命令,则输出以下结果:

@angular/cli: 1.1.1
node: 6.10.2
os: darwin x64

安装完 Angular CLI,接下来我们来使用它创建新的应用程序。

创建新的 Angular 应用程序

Angular CLI 为我们提供了两种方式,用于创建新的应用程序:

  • ng init - 在当前目录创建新的应用程序
  • ng new - 创建新的目录,然后在新建的目录中运行 ng init 命令

因此 ng newng init 的功能是相似的,只是 ng new 会为我们创建新的目录。

假设你还未创建新的目录,那么我们需要使用 ng new 命令来创建新的项目:

$ ng new my-app

当运行上面的命令后,将发生以下事情:

  • 新的 my-app 目录被创建
  • 应用程序相关的源文件和目录将会被创建
  • 应用程序的所有依赖 (package.json中配置的依赖项) 将会被自动安装
  • 自动配置项目中的 TypeScript 开发环境
  • 自动配置 Karma 单元测试环境
  • 自动配置 Protractor (end-to-end) 测试环境
  • 创建 environment 相关的文件并初始化为默认的设置

此时 my-app 目录中 Angular 应用程序的目录结构如下:

.
├── README.md
├── e2e
│   ├── app.e2e-spec.ts
│   ├── app.po.ts
│   └── tsconfig.e2e.json
├── karma.conf.js
├── package.json
├── protractor.conf.js
├── src
│   ├── app
│   │   ├── app.component.css
│   │   ├── app.component.html
│   │   ├── app.component.spec.ts
│   │   ├── app.component.ts
│   │   └── app.module.ts
│   ├── assets
│   ├── environments
│   │   ├── environment.prod.ts
│   │   └── environment.ts
│   ├── favicon.ico
│   ├── index.html
│   ├── main.ts
│   ├── polyfills.ts
│   ├── styles.css
│   ├── test.ts
│   ├── tsconfig.app.json
│   ├── tsconfig.spec.json
│   └── typings.d.ts
├── tsconfig.json
└── tslint.json

可用选项

  • --dry-run: boolean, 默认为 false, 若设置 dry-run 则不会创建任何文件
  • --verbose: boolean, 默认为 false
  • --link-cli: boolean, 默认为 false, 自动链接到 @angular/cli
  • --skip-install: boolean, 默认为 false, 表示跳过 npm install
  • --skip-git: boolean, 默认为 false, 表示该目录不初始化为 git 仓库
  • --skip-tests: boolean, 默认为 false, 表示不创建 tests 相关文件
  • --skip-commit: boolean, 默认为 false, 表示不进行初始提交
  • --directory: string, 用于设置创建的目录名,默认与应用程序的同名
  • --source-dir: string, 默认为 'src', 用于设置源文件目录的名称
  • --style: string, 默认为 'css', 用于设置选用的样式语法 ('css', 'less' or 'scss')
  • --prefix: string, 默认为 'app', 用于设置创建新组件时,组件选择器使用的前缀
  • --mobile: boolean, 默认为 false,表示是否生成 Progressive Web App 应用程序
  • --routing: boolean, 默认为 false, 表示新增带有路由信息的模块,并添加到根模块中
  • --inline-style: boolean, 默认为 false, 表示当创建新的应用程序时,使用内联样式
  • --inline-template: boolean, 默认为 false, 表示当创建新的应用程序时,使用内联模板

除此之外,你可以在本机上运行 ng generate --help 查看更多的可用选项。接下来让我们来看一下如何运行应用程序。

运行应用程序

首先进入使用 Angular CLI 创建的应用程序目录,例如:

$ cd my-app

然后运行:

$ ng serve

当运行上面的命令后,将发生以下事情:

  • Angular CLI 从 .angular-cli.json 文件中加载配置信息
  • Angular CLI 运行 Webpack 打包相关 JavaScript 和 CSS 文件
  • Angular CLI 启动 webpack dev server 本地开发服务器,默认的地址是 localhost:4200

若要停止应用程序,你可以使用 ctrl+c 快捷键。

添加功能到现有的 Angular 应用程序

你可以使用 ng generate 命令,为已有的 Angular 应用程序添加新的功能。

  • ng generate class my-new-class: 新建 class
  • ng generate component my-new-component: 新建组件
  • ng generate directive my-new-directive: 新建指令
  • ng generate enum my-new-enum: 新建枚举
  • ng generate module my-new-module: 新建模块
  • ng generate pipe my-new-pipe: 新建管道
  • ng generate service my-new-service: 新建服务

ng generate 命令与其它的子命令一样,也有快捷键,具体如下:

  • ng g cl my-new-class: 新建 class
  • ng g c my-new-component: 新建组件
  • ng g d my-new-directive: 新建指令
  • ng g e my-new-enum: 新建枚举
  • ng g m my-new-module: 新建模块
  • ng g p my-new-pipe: 新建管道
  • ng g s my-new-service: 新建服务

添加新的类

为了添加类名为 UserProfile 类,我们可以运行:

$ ng generate class user-profile

Angular CLI 会自动调整文件名和类名的字母大小写,因此以下命令具有相同的效果:

$ ng generate class user-profile
$ ng generate class userProfile
$ ng generate class UserProfile

运行上述命令后,在幕后将发生以下事情:

  • src/app 目录下将创建一个 user-profile.ts 文件,该文件导出一个名为 UserProfile 的类

可用选项

  • --spec: boolean, 默认为 false, 表示是否生成单元测试相关的 spec 文件

使用示例

# Generate class 'UserProfile'
$ ng generate class user-profile

# Generate class 'UserProfile' with unit test
$ ng generate class user-profile --spec

添加新的组件

若想创建一个选择器为 app-site-header 的组件,则可以运行:

$ ng generate component site-header
installing component
  create src/app/site-header/site-header.component.css
  create src/app/site-header/site-header.component.html
  create src/app/site-header/site-header.component.spec.ts
  create src/app/site-header/site-header.component.ts
  update src/app/app.module.ts

Angular CLI 将自动调整文件名和组件名称的字母大小写,并将前缀应用于组件选择器,因此以下命令具有相同的效果:

$ ng generate component site-header
$ ng generate component siteHeader
$ ng generate component SiteHeader

运行上述命令后,在幕后将发生以下事情:

  • src/app/site-header 目录被创建
  • site-header 目录下会生成以下四个文件:

    • CSS 样式文件,用于设置组件的样式
    • HTML 模板文件,用于设置组件的模板
    • TypeScript 文件,里面包含一个 SiteHeaderComponent 组件类和组件的元信息
    • Spec 文件,包含组件相关的测试用例
  • SiteHeaderComponent 组件会被自动地添加到最近模块 @NgModule 装饰器的 declarations 属性中。

可用选项

  • --flat: boolean, 默认为 false, 表示在 src/app 目录下生成组件而不是在 src/app/site-header 目录中
  • --inline-template: boolean, 默认为 false, 表示使用内联模板而不是使用独立的模板文件
  • --inline-style: boolean, 默认为 false, 表示使用内联样式而不是使用独立的样式文件
  • --prefix: boolean, 默认为 true, 使用 .angular-cli.json 配置的前缀作为组件选择器的前缀
  • --spec: boolean, 默认为 true, 表示生成包含单元测试的 spec 文件
  • --view-encapsulation: string, 用于设置组件的视图封装策略
  • --change-detection: string, 用于设置组件的变化检测策略

使用示例

# Generate component 'site-header'
$ ng generate component site-header

# Generate component 'site-header' with inline template and inline styles
$ ng generate component site-header --inline-template --inline-style

添加新的指令

若想创建一个选择器为 appAdminLink 的指令,则可以运行:

$ ng generate directive admin-link
installing directive
  create src/app/admin-link.directive.spec.ts
  create src/app/admin-link.directive.ts
  update src/app/app.module.ts

Angular CLI 将自动调整文件名和指令名称的字母大小写,并将前缀应用于指令选择器,因此以下命令具有相同的效果:

$ ng generate directive admin-link
$ ng generate directive adminLink
$ ng generate directive AdminLink

运行上述命令后,在幕后将发生以下事情:

  • src/app/admin-link.directive.ts 文件被创建,该文件导出一个名为 AdminLinkDirective 且选择器为 appAdminLink 的指令
  • src/app/admin-link.directive.spec.ts 文件被创建,该文件包含指令相关的单元测试信息
  • AdminLinkDirective 指令会被自动地添加到最近模块 @NgModule 装饰器的 declarations 属性中。

可用选项

  • --flat: boolean, 默认为 true, 表示在 src/app 目录中生成指令而不是在 src/app/admin-link 目录下
  • --prefix: boolean, 默认为 true, 使用 .angular-cli.json 配置的前缀作为指令选择器的前缀
  • --spec: boolean, 默认为 true, 表示生成包含单元测试的 spec 文件

使用示例

# Generate directive 'adminLink'
$ ng generate directive admin-link

# Generate directive 'adminLink' without unit test
$ ng generate directive admin-link --spec=false

添加新的枚举

若想创建一个名为 Direction 的枚举类 ,则可以运行:

$ ng generate enum direction
installing enum
  create src/app/direction.enum.ts

Angular CLI 会自动调整文件名和枚举名称的字母大小写,因此以下命令具有相同的效果:

$ ng generate enum direction
$ ng generate enum Direction

运行上述命令后,在幕后将发生以下事情:

  • src/app.direction.enum.ts 文件被创建,该文件导出名为 Direction 的枚举

添加新的模块

若想创建一个新的模块 ,则可以运行:

$ ng generate module admin
installing module
  create src/app/admin/admin.module.ts

运行上述命令后,在幕后将发生以下事情:

  • src/app/admin 目录被创建
  • src/app/admin/admin.module.ts 文件中,AdminModule 模块被创建

需要注意的是,新增的模块不会被自动添加到 src/app/app.module.ts 文件中的 AppModule 模块中,用户可以根据具体需求导入对应的模块。

若要在其它模块中导入刚才新增的模块,可以在 @NgModuleimports 属性中设定该新增的模块。具体示例如下:

import { AdminModule } from './admin/admin.module';

@NgModule({
  // ...
  imports: [
    AdminModule
  ]
})
export class AppModule { }

可用选项

  • --routing: boolean, 默认为 false, 表示生成一个额外包含路由信息的 AdminRoutingModule 模块,且该模块会被自动地导入到新建的模块中
  • --spec: boolean, 默认为 false, 表示添加 src/app/admin/admin.module.spec.ts 单元测试文件

使用示例

# Add module 'admin'
$ ng generate module admin

# Add module 'admin' with additional module containing routing information
$ ng generate module admin --routing

添加新的管道

若想创建一个名为 convertToEuro 的管道 ,则可以运行:

$ ng generate pipe convert-to-euro
installing pipe
  create src/app/convert-to-euro.pipe.spec.ts
  create src/app/convert-to-euro.pipe.ts
  update src/app/app.module.ts

Angular CLI 会自动调整文件名和管道名称的字母大小写,因此以下命令具有相同的效果:

$ ng generate pipe convert-to-euro
$ ng generate pipe convertToEuro
$ ng generate pipe ConvertToEuro

运行上述命令后,在幕后将发生以下事情:

  • src/app/convert-to-euro.pipe.ts 文件被创建,该文件导出一个名为 ConvertToEuroPipe 的管道类
  • src/app/convert-to-euro.pipe.spec.ts 文件被创建,该文件包含管道相关的单元测试信息
  • CovertToEuroPipe 管道会被自动地添加到最近模块 @NgModule 装饰器的 declarations 属性中。

可用选项

  • --flat: boolean, 默认为 true, 表示在 src/app 目录中生成管道而不是在 src/app/convert-to-euro 目录下
  • --spec: boolean, 默认为 true, 表示生成包含单元测试的 spec 文件

使用示例

# Generate pipe 'convertToEuro' with spec and in /src/app directory
$ ng generate pipe convert-to-euro

# Generate pipe 'convertToEuro' without spec and in /src/app/convert-to-euro directory
$ ng generate pipe convert-to-euro --spec=false --flat=false

添加新的服务

若想创建一个名为 BackendApiService 的服务 ,则可以运行:

$ ng generate service backend-api
installing service
  create src/app/backend-api.service.spec.ts
  create src/app/backend-api.service.ts
  WARNING Service is generated but not provided, it must be provided to be used

Angular CLI 会自动调整文件名和服务名称的字母大小写,因此以下命令具有相同的效果:

$ ng generate service backend-api
$ ng generate service backendApi
$ ng generate service BackendApi

运行上述命令后,在幕后将发生以下事情:

  • src/app/backend-api.service 文件被创建,该文件导出一个名为 BackendApiService 的服务类
  • src/app/back-api.service.spec.ts 文件被创建,该文件包含管道相关的单元测试信息

需要注意的是,Angular CLI 会提醒用户服务已成功创建,但尚未配置该服务。用户可以根据具体需求在模块或组件的 providers 属性中配置该新建的服务。具体示例如下:

import { BackendApiService } from './backend-api.service';

@NgModule({
  // ...
  providers: [BackendApiService],
  bootstrap: [AppComponent]
})

可用选项

  • --flat: boolean, 默认为 true, 表示在 src/app 目录中生成服务而不是在 src/app/backend-api 目录下
  • --spec: boolean, 默认为 true, 表示生成包含单元测试的 spec 文件

使用示例

# Generate service with DI token 'BackendApiService' in /src/app directory
$ ng generate service backend-api

# Generate service with DI token 'BackendApiService' in /src/app/backend-api directory
$ ng generate service backend-api --flat=false

运行单元测试

Angular CLI 在新建项目的时候,自动为我们集成了 Karma test runner 测试框架。当添加新的功能时,我们可以利用 --spec 选项,告诉 Angular CLI 让它为我们生成功能相关的 .spec.ts 测试单元测试文件。

spec 文件在 src 目录中相应功能的同一目录下创建,这使得我们可以在使用功能时轻松找到它们。

若要运行单元测试,则可以运行:

$ ng test

此时在你的控制台将输出以下信息:

$ ng test
[karma]: No captured browser, open http://localhost:9876/
[karma]: Karma v1.4.1 server started at http://0.0.0.0:9876/
[launcher]: Launching browser Chrome with unlimited concurrency
[launcher]: Starting browser Chrome

运行上述命令后,在幕后将发生以下事情:

  • Angular CLI 从 .angular-cli.json 文件中加载配置信息
  • Angular CLI 基于 .angular-cli.json 文件中的 Karma 相关的配置信息,运行 Karma。Karma 的配置文件默认在根目录下,文件名为 karma.conf.js
  • Karma 打开配置中设定的浏览器,默认是 Chrome
  • Karma 然后指示浏览器 (Chrome) 使用 Karma 配置中指定的测试框架运行 src/test.ts。默认情况下,采用的是 Jasmine 框架。创建应用程序时,会自动创建 src/test.ts 文件。它预先配置为加载和配置测试Angular 应用程序所需的代码,并运行 src 目录中以 .spec.ts 结尾的所有文件。
  • Karma 将测试结果报告给控制台。
  • Karma 监听 src 目录下的文件的变化,然后自动运行单元测试。

运行 End-to-End 测试

若要运行 e2e 测试,则可以运行:

$ ng e2e

构建应用程序

若要构建应用程序,则可以运行:

$ ng build

运行上述命令后,在幕后将发生以下事情:

  • Angular CLI 从 .angular-cli.json 文件中加载配置信息
  • Angular CLI 运行 Webpack 打包项目相关的 JavaScript 与 CSS 文件
  • 打包后的资源,将被输出到配置文件中 outDir 所指定的目录,默认是输出到 dist 目录

可用选项

  • --aot: 开启 ahead-of-time 编译
  • --base-href: string, 设置 index.html 文件中 <base> 元素的链接地址
  • --environment: string, 设置所使用的环境,默认为 dev
  • --output-path: string, 设置输出的路径
  • --target: string, 设置所使用的环境,默认为 development
  • --watch: boolean, 默认为 false, 开启 watch 模式,监听文件异动并自动重新构建

Targets

指定 target 的值,会影响到构建流程的运行方式。它的可选值:

  • development: 默认的模式,意味着不进行代码压缩或混淆
  • production: 压缩和混淆代码

若需使用 production 模式,构建应用程序,则可以运行:

$ ng build --target=production

Environments

Environments 让你能够自定义应用程序行为。

你可以在 .angular-cli.json 文件中定义自己的 environments 文件。默认的是:

  • dev:environments/environment.ts
export const environment = {
  production: false
};
  • prod:environments/environment.prod.ts
export const environment = {
  production: true
};

需要注意的是,构建流程默认使用 dev 环境。

如果指定了不同的环境,构建过程将使用相应的环境:

# Uses environments/environment.ts
$ ng build

# Also uses environments/environment.ts
$ ng build --environment=dev
$ ng build --env=dev

# Uses environments/environment.prod.ts
$ ng build --environment=prod
$ ng build --env=prod

正如你在 src/main.ts 文件中看到的,通过导入 ./environments/environment 文件,我们就可以访问到 environment 相关的配置信息,具体如下:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

自定义构建流程

从 v1.0 开始,Angular CLI 提供了一个命令,用于将你的应用程序与 Angular CLI 分离。

默认情况下,Angular CLI 为您管理基础 Webpack 配置,因此您无需处理其复杂性。如果你希望手动配置webpack,并且您不再需要在Angular应用程序中使用Angular CLI,则可以运行:

$ ng eject

此时在你的控制台将输出以下信息:

==========================================================================================
Ejection was successful.

To run your builds, you now need to do the following commands:
   - "npm run build" to build.
   - "npm run test" to run unit tests.
   - "npm start" to serve the app using webpack-dev-server.
   - "npm run e2e" to run protractor.

Running the equivalent CLI commands will result in an error.

==========================================================================================
Some packages were added. Please run "npm install".

运行上述命令后,在幕后将发生以下事情:

  • ejected: true 的属性被添加到 .angular-cli.json 文件中
  • 在应用程序的根目录下将生成独立的 webpack.config.js 文件,因此你可以在没有使用 Angular CLI 的环境下构建项目
  • package.json 中的构建脚本会被更新,因此你可以运行 npm run build 来构建项目
  • package.json 中的测试脚本会被更新,因此你可以运行 npm run test 来运行单元测试
  • package.json 中的启动脚本会被更新,因此你可以运行 npm run startnpm start 来启动开发服务器
  • package.json 中的 e2e 脚本会被更新,因此你可以运行 npm run e2e 来运行 End-to-End 测试

把应用程序与 Angular CLI 分离后,你就可以根据自己的要求自定义 Webpack 的配置。

参考资源

查看原文

smart_dream 回答了问题 · 2018-04-16

chart.js 显示具体数值

clipboard.png

      options: {
        animation: {
          duration: 2000,
          onComplete: function() {
            var chart = this.chart;
            var ctx = chart.ctx;

            this.data.datasets.forEach(function(dataset, i) {
              var meta = chart.controller.getDatasetMeta(i);
              if (!meta.hidden) {
                meta.data.forEach(function(element, index) {
                  // Draw the text in black, with the specified font
                  ctx.fillStyle = layoutColors.defaultText;
                  var fontSize = 16;
                  ctx.font = Chart.helpers.fontString(fontSize, 'normal', 'Helvetica Neue');

                  // Just naively convert to string for now
                  var dataString = dataset.data[index].toString();

                  // Make sure alignment settings are correct
                  ctx.textAlign = 'center';
                  ctx.textBaseline = 'middle';

                  var padding = 5;
                  var position = element.tooltipPosition();
                  ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
                });
              }
            });
          }
        }
      }

关注 4 回答 3

smart_dream 赞了回答 · 2018-04-16

chart.js 显示具体数值

options 中加入

"animation": {
      "duration": 1,
      "onComplete": function() {
        var chartInstance = this.chart,
          ctx = chartInstance.ctx;

        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        this.data.datasets.forEach(function(dataset, i) {
          var meta = chartInstance.controller.getDatasetMeta(i);
          meta.data.forEach(function(bar, index) {
            var data = dataset.data[index];
            ctx.fillText(data, bar._model.x, bar._model.y - 5);
          });
        });
      }
    },

chartjs 版本要2.5以上

参考链接

关注 4 回答 3

smart_dream 回答了问题 · 2017-11-06

解决react中使用阿里彩色iconfont,控制到报错

<use xlink:href="#my-icon" />
href引用里面应该有 “ # ”

关注 2 回答 3

smart_dream 赞了回答 · 2017-10-31

ng-repeat遍历数组在tr中的th展示数据,其中一个字段是json对象

写一个filter, 比如

angular.filter('keyValuePairs', ()=> e => `${e.key}-${e.value}`)

然后

{{template.Params | keyValuePairs}}

关注 5 回答 5

smart_dream 赞了回答 · 2017-10-20

解决为什么选择器:last-child没有起作用?

el:last-child 的匹配规则是:第一步,查找 el 选择器匹配元素的所有同级元素(siblings);第二步,在同级元素中查找最后一个元素;第三步,检验最后一个元素是否与选择器 el 匹配。

.list:last-child 匹配到了 footer,但 footer 不匹配 .list,故选择器不生效。

相比用 last-of-type,一个可能更好的方案是:将所有 p 标签用一个父元素包起来,然后用:
.list:not(:last-child) {} // 不兼容 IE9-

关注 7 回答 6

认证与成就

  • 获得 4 次点赞
  • 获得 13 枚徽章 获得 1 枚金徽章, 获得 1 枚银徽章, 获得 11 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-12-18
个人主页被 269 人浏览