Angular4 中文文档


第一节 Angular 简介

Angular 是什么

Angular 是由谷歌开发与维护一个开发跨平台应用程序的框架,同时适用于手机与桌面。

Angular 有什么特点

 

基于 Angular 我们可以构建适用于所有平台的应用。比如:Web 应用、移动 Web 应用、移动应用和桌面应用等。

 

通过 Web Worker和服务端渲染 (SSR),达到在如今Web平台上所能达到的最高渲染速度。

 

Angular 让你能够有效掌控可伸缩性。基于 RxJS、Immutable.js 和其它推送模型,能适应海量数据需求。

 

Angular 提供了哪些功能

 

动态HTML

强大的表单系统 (模板驱动和模型驱动)

强大的视图引擎

事件处理

快速的页面渲染

灵活的路由

HTTP 服务

视图封装

AOT、Tree Shaking

Angular 与 AngularJS 有什么区别

不再有Controller和 Scope

更好的组件化及代码复用

更好的移动端支持

引入了 RxJS 与 Observable

引入了 Zone.js,提供更加智能的变化检测

第二节 – Angular 环境搭建

基础要求

Node.js

Git

Angular 开发环境配置方式

基于 Angular Quickstart

https://github.com/angular/qu…

基于 Angular CLI

npm install -g @angular/cli

配置开发环境

本快速入门教程,选用第一种配置方式搭建 Angular 开发环境:

基于 Angular Quickstart

使用 Git 克隆 quickstart 项目

git clone https://github.com/angular/quickstart ng4-quickstart

使用 IDE 打开已新建的项目 (本教程使用的 IDE 是 Visual Studio Code)

code ./ng4-quickstart

安装项目所需依赖

npm i

验证环境是否搭建成功

npm start

基于 Angular CLI

Angular团队为开发者提供了一个开箱即用(out of the box)的脚手架工具:Angular Cli。我们再也不用担心在项目初始化时,要搭建配置一系列的工具,比如webpack,karma,tslint,protractor等。

操作很简单,只要运行如下命令行就搞定了。

安装 Angular CLI (可选)

npm install -g @angular/cli

检测 Angular CLI 是否安装成功

ng –version

创建新的项目

ng new PROJECT-NAME

启动本地服务器

cd PROJECT-NAME

ng serve

安装之后,文件目录如下:

my-dream-app

e2e                      // 端到端测试

app.e2e-spec.ts

app.po.ts

tsconfig.e2e.json

node_modules/…         // npm包

src/…                  // 源码

angular-cli.json         // 配置项

.editorconfig            // 编辑器配置

.gitignore               // git忽略文件配置

karma.conf.js            // karma配置

package.json             // npm配置

protractor.conf.js       // 测试配置项

README.md                // 项目说明

tsconfig.json            // ts编辑器的配置

tslint.json              // tslint配置项

 

我们需要关注的是src文件夹,这里存放我们所有的源代码,开发的时候基本都在src中。

src

app                      // 代码的主要文件夹

app.component.css    // 根组件样式

app.component.html   // 根组件模版

app.component.spec.ts// 根组件测试

app.component.ts     // 根组件脚本

app.module.ts        // 根模块

assets                   // 静态资源

.gitkeep             // 保存空文件夹

environments             // 环境配置

environment.prod.ts

environment.ts

favicon.ico              // 图标

index.html               // 页面主入口

main.ts                  // 脚本主入口

polyfills.ts             // 兼容浏览器

styles.css               // 全局css样式

test.ts                  // 单元测试主入口

模块

Angular很重要的概念之一仍然是模块。Angular整个框架就是由很多个模块组成的,而不同的模块需要从不同的地方导入。打开package.json文件,可以看到依赖的angular包可能是这样的:

“@angular/common”: “^2.3.1″,”@angular/compiler”: “^2.3.1″,”@angular/core”: “^2.3.1″,”@angular/forms”: “^2.3.1″,”@angular/http”: “^2.3.1″,”@angular/platform-browser”: “^2.3.1″,”@angular/platform-browser-dynamic”: “^2.3.1″,”@angular/router”: “^3.3.1”,

来简单看下这些angular包中包含了哪些常用的模块(至少目前为止,我觉得常用的)。

@angular/core:这里包含了很多常用的模块

NgModule:模块定义装饰器

Component:组件定义装饰器

Directive:指令定义装饰器

Pipe :管道定义装饰器

PipeTransform:管道接口

Injectable:服务定义装饰器

ElmentRef:元素引用

ViewChild:获取子元素

Render:渲染

Input:接受参数输入

Output:事件输出

EventEmitter:触发自定义事件

@angular/common

CommonModule:通用模块,包含内置指令ngIf,ngFor

@angular/forms

FormsModule:定义模版驱动表单

ReactiveFormsModule:定义响应式表单

FormGroup, FormArray, FormControl, FormBuilder:响应式表单元素

Validators:表单校验

@angular/http

HttpModule:http请求模块

@angular/router

RouterModule 路由模块

Routes 路由数据结构

@angular/platform-browser

platformBrowser:AoT编译

BrowserModule:浏览器支持,注意该模块导入了CommonModule,然后导出去,所以引用了这个模块也就引用了CommonModule

@angular/platform-browser-dynamic

platformBrowserDynamic:JIT编译

以上模块都是Angular框架中的自带模块,而我们开发的完整单元也是模块。一个应用中至少要有一个模块,也就是根模块。 一些共享的功能属性我们可以抽象出来,成为共享模块。然后就是一些特性模块了。

模块的组成由组件,服务,指令,管道等等组成,这些概念会在下面讲到。定义模块的语法如下:

@NgModuel({

declarations: [],   // 用到的组件,指令,管道

providers: [],      // 依赖注入服务

imports: [],        // 导入需要的模块

exports: [],        // 导出的模块,跨模块交流

entryComponents: [] // 需提前编译好的模块

bootstrap: []       // 设置根组件

 

})

export class AppModule { }

所有用到的组件,指令,管道,模块都需要事先在模块中声明好,才能在具体组件中使用。服务可以在模块,组件,指令中的providers声明,也可以直接在运行时提供(参见Trotyl Yu的例子)。

一般情况下,在根模块的bootstrap中设置启动的根组件即可,但也可以动态处理(参见Trotyl Yu的例子)。

那如何启动根模块呢?

在入口脚本中,也就是Angular Cli项目中的main.ts中,启动如下:

// 导入需要模块import { platformBrowserDynamic } from ‘@angular/platform-browser-dynamic’;

// 根模块import { AppModule } from ‘./app/app.module’;

// 编译启动模块

platformBrowserDynamic().bootstrapModule(AppModule);

至此,我们对模块有所了解,也知道了模块的定义。

 

 

第三节 – 插值表达式

在 Angular 中,我们可以使用 {{}} 插值语法实现数据绑定。

绑定普通文本

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `<h1>Hello {{name}}</h1>`,

})export class AppComponent  {

name = ‘Angular’;

}

绑定对象属性

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `

<h2>大家好,我是{{name}}</h2>

<p>我来自<strong>{{address.province}}</strong>省,

<strong>{{address.city}}</strong>市

</p>

`,

})export class AppComponent {

name = ‘Semlinker’;

address = {

province: ‘福建’,

city: ‘厦门’

}

}

值得一提的是,我们可以使用 Angular 内置的 json 管道,来显示对象信息:

@Component({

selector: ‘my-app’,

template: `

<p>{{address | json}}</p>

`,

})export class AppComponent {

name = ‘Semlinker’;

address = {

province: ‘福建’,

city: ‘厦门’

}

}

第四节 – 自定义组件

在 Angular 中,我们可以通过 Component 装饰器和自定义组件类来创建自定义组件。

基础知识

定义组件的元信息

在 Angular 中,我们可以使用 Component 装饰器来定义组件的元信息:

@Component({

selector: ‘my-app’, // 用于定义组件在HTML代码中匹配的标签

template: `<h1>Hello {{name}}</h1>`, // 定义组件内嵌视图

})

定义组件类

export class AppComponent  {

name = ‘Angular’;

}

定义数据接口

在 TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。

interface Person {

name: string;

age: number;

}

let semlinker: Person = {

name: ‘semlinker’,

age: 31

};

自定义组件示例

创建 UserComponent 组件

import { Component } from ‘@angular/core’;

@Component({

selector: ‘sl-user’,

template: `

<h2>大家好,我是{{name}}</h2>

<p>我来自<strong>{{address.province}}</strong>省,

<strong>{{address.city}}</strong>市

</p>

`

})export class UserComponent {

name = ‘Semlinker’;

address = {

province: ‘福建’,

city: ‘厦门’

};

}

声明 UserComponent 组件

// …import { UserComponent } from ‘./user.component’;@NgModule({

imports:      [ BrowserModule ],

declarations: [ AppComponent, UserComponent],

bootstrap:    [ AppComponent ]

})export class AppModule { }

使用 UserComponent 组件

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `

<sl-user></sl-user>

`,

})export class AppComponent {}

使用构造函数初始化数据

@Component({…})export class UserComponent {

name: string;

address: any;

 

constructor() {

this.name = ‘Semlinker’;

this.address = {

province: ‘福建’,

city: ‘厦门’

}

}

}

接口使用示例

定义 Address 接口

interface Address {

province: string;

city: string;

}

使用 Address 接口

export class UserComponent {

name: string;

address: Address;

// …

}

组件生命周期

正如其他框架的组件,Angular的组件也是有生命周期这个概念。在不同的阶段不同的场景下,可以调用不同的生命周期函数钩子(hook)。

constructor:构造器函数,一般用于注入服务

ngOnChanges:检测到输入数据变化,首次触发发生在ngOnInit前。注意对象的属性发生变化时监听不到

ngOnInit:组件初始化,通常会设置一些初始值

ngDoCheck:手动触发更新检查

ngAfterContentInit:内容初始化到组件之后

ngAfterContentChecked:内容变更检测之后

ngAfterViewInit:视图 初始化之后

ngAfterViewChecked:视图发生变化检测之后,这个可以用来保证用户视图的及时更新

ngOnDestroy:组件注销时的清理工作,通常用于移除事件监听,退订可观察对象等

组件通信

可以想像得到,组件化的页面结构最终会形成一颗组件树。盗一张Vue的图:不可避免,我们需要考虑父子组件之间的参数传递问题。Anuglar提供的通信方式有如下几种:

父组件到子组件:父组件用属性绑定将值传入,子组件通过@Input来接收。

// 父组件import { Component } from ‘@angular/core’;

 

@Component({

selector: ‘hero-parent’,

template: `<h2> heroes </h2>

<hero-child *ngFor=”let hero of heroes”

[hero]=”hero” >

</hero-child>

`

})export class HeroParentComponent {

heroes = [{

name: ‘John’

}, {

name: ‘Lily’

}];

}

// 子组件import { Component, Input } from ‘@angular/core’;

import { Hero } from ‘./hero’;

@Component({

selector: ‘hero-child’,

template: `

<h3>{{hero.name}}</h3>

`

})export class HeroChildComponent {

@Input() hero: Hero;

}

子组件到父组件:子组件自定义事件用@Output传出,父组件用事件绑定获取。

// 子组件import { Component, EventEmitter, Output } from ‘@angular/core’;

@Component({

  selector: ‘my-voter’,

  template: `

    <h4>{{name}}</h4>

    <button (click)=”vote(true)”>Agree</button>

`

})

export class VoterComponent {

@Output() onVoted = new EventEmitter<boolean>();

vote(agreed: boolean) {

this.onVoted.emit(agreed);

}

}

// 父组件import { Component } from ‘@angular/core’;

@Component({

  selector: ‘vote-taker’,

  template: `

    <h2>Should mankind colonize the Universe?</h2>

    <h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>

    <my-voter *ngFor=”let voter of voters”

      [name]=”voter”

      (onVoted)=”onVoted($event)”>

</my-voter>

`

})

export class VoteTakerComponent {

agreed = 0;

disagreed = 0;

voters = [‘Mr. IQ’, ‘Ms. Universe’, ‘Bombasto’];

onVoted(agreed: boolean) {

agreed ? this.agreed++ : this.disagreed++;

}

}

 

子组件引用:在父组件模版中添加对子组件的引用,即可通过该子组件去访问子组件的方法。

 

<h3>Countdown to Liftoff (via local variable)</h3><button (click)=”timer.start()”>Start</button><button (click)=”timer.stop()”>Stop</button><div class=”seconds”>{{timer.seconds}}</div><countdown-timer #timer></countdown-timer>

@ViewChild():类似的,也可以在脚本中用@ViewChild()来获取子组件

 

import { AfterViewInit, ViewChild } from ‘@angular/core’;import { Component }                from ‘@angular/core’;import { CountdownTimerComponent }  from ‘./countdown-timer.component’;

@Component({

selector: ‘countdown-parent-vc’,

template: `

<h3>Countdown to Liftoff (via ViewChild)</h3>

<button (click)=”start()”>Start</button>

<button (click)=”stop()”>Stop</button>

<div class=”seconds”>{{ seconds() }}</div>

<countdown-timer></countdown-timer>

`

})export class CountdownViewChildParentComponent implements AfterViewInit {

@ViewChild(CountdownTimerComponent)

private timerComponent: CountdownTimerComponent;

seconds() { return 0; }

ngAfterViewInit() {

setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);

}

start() { this.timerComponent.start(); }

stop() { this.timerComponent.stop(); }

}

将数据保存在服务中

@ngrx/store:参见http://blog.csdn.net/fen747042796/article/details/74840844

第五节 – 常用指令简介

在 Angular 实际项目中,最常用的指令是 ngIf 和 ngFor 指令。

基础知识

ngIf 指令简介

该指令用于根据表达式的值,动态控制模板内容的显示与隐藏。它与 AngularJS 1.x 中的 ng-if 指令的功能是等价的。

ngIf 指令语法

<div *ngIf=”condition”>…</div>

ngFor 指令简介

该指令用于基于可迭代对象中的每一项创建相应的模板。它与 AngularJS 1.x 中的 ng-repeat 指令的功能是等价的。

ngFor 指令语法

<li *ngFor=”let item of items;”>…</li>

ngIf 与 ngFor 指令使用示例

import { Component } from ‘@angular/core’;

interface Address {

province: string;

city: string;

}

@Component({

selector: ‘sl-user’,

template: `

<h2>大家好,我是{{name}}</h2>

<p>我来自<strong>{{address.province}}</strong>省,

<strong>{{address.city}}</strong>市

</p>

<div *ngIf=”showSkills”>

<h3>我的技能</h3>

<ul>

<li *ngFor=”let skill of skills”>

{{skill}}

</li>

</ul>

</div>

`

})export class UserComponent {

name: string;

address: Address;

showSkills: boolean;

skills: string[];

constructor() {

this.name = ‘Semlinker’;

this.address = {

province: ‘福建’,

city: ‘厦门’

};

this.showSkills = true;

this.skills = [‘AngularJS 1.x’, ‘Angular 2.x’, ‘Angular 4.x’];

}

}

NgSwitch

有时候需要根据不同的条件,渲染不同的元素,此时我们可以使用多个 ngIf 来实现。

<div class=”container”>

<div *ngIf=”myVar == ‘A'”>Var is A</div>

<div *ngIf=”myVar == ‘B'”>Var is B</div>

<div *ngIf=”myVar != ‘A’ && myVar != ‘B'”>Var is something else</div>

</div>

如果 myVar 的可选值多了一个 ‘C’,就得相应增加判断逻辑:

<div class=”container”>

<div *ngIf=”myVar == ‘A'”>Var is A</div>

<div *ngIf=”myVar == ‘B'”>Var is B</div>

<div *ngIf=”myVar == ‘C'”>Var is C</div>

<div *ngIf=”myVar != ‘A’ && myVar != ‘B’ && myVar != ‘C'”>

Var is something else

</div>

</div>

可以发现 Var is something else 的判断逻辑,会随着 myVar 可选值的新增,变得越来越复杂。遇到这种情景,我们可以使用 ngSwitch 指令。

<div class=”container” [ngSwitch]=”myVar”>

<div *ngSwitchCase=”‘A'”>Var is A</div>

<div *ngSwitchCase=”‘B'”>Var is B</div>

<div *ngSwitchCase=”‘C'”>Var is C</div>

<div *ngSwitchDefault>Var is something else</div>

</div>

NgStyle

NgStyle 让我们可以方便得通过 Angular 表达式,设置 DOM 元素的 CSS 属性。

1、设置元素的背景颜色

<div [style.background-color=”‘yellow'”]>

Use fixed yellow background

</div>

2、设置元素的字体大小

<!– 支持单位: px | em | %–>

<div>

<span [ngStyle]=”{color: ‘red’}” [style.font-size.px]=”fontSize”>

red text

</span>

</div>

NgStyle 支持通过键值对的形式设置 DOM 元素的样式:

<div [ngStyle]=”{color: ‘white’, ‘background-color’: ‘blue’}”>

Uses fixed white text on blue background

</div>

注意到 background-color 需要使用单引号,而 color 不需要。这其中的原因是,ng-style 要求的参数是一个 Javascript 对象,color 是一个有效的 key,而 background-color 不是一个有效的 key ,所以需要添加 ”。

NgClass

NgClass 接收一个对象字面量,对象的 key 是 CSS class 的名称,value 的值是 truthy/falsy 的值,表示是否应用该样式。

1、CSS Class

.bordered {

border: 1px dashed black; background-color: #eee;

}

2、HTML

<!– Use boolean value –>

<div [ngClass]=”{bordered: false}”>This is never bordered</div>

<div [ngClass]=”{bordered: true}”>This is always bordered</div>

 

<!– Use component instance property –>

<div [ngClass]=”{bordered: isBordered}”>

Using object literal. Border {{ isBordered ? “ON” : “OFF” }}

</div>

 

<!– Class names contains dashes –>

<div[ngClass]=”{‘bordered-box’: false}”>

Class names contains dashes must use single quote

</div>

 

<!– Use a list of class names –>

<div class=”base” [ngClass]=”[‘blue’, ’round’]”>

This will always have a blue background and round corners

</div>

NgNonBindable

ngNonBindable 指令用于告诉 Angular 编译器,无需编译页面中某个特定的HTML代码片段。

<div class=’ngNonBindableDemo’>

<span class=”bordered”>{{ content }}</span>

<span class=”pre” ngNonBindable>

← This is what {{ content }} rendered

</span>

</div>

Angular 4.x 新特性

If…Else Template Conditions

语法

<element *ngIf=”[condition expression]; else [else template]”></element>

使用示例

<ng-template #hidden>

<p>You are not allowed to see our secret</p>

</ng-template>

<p *ngIf=”shown; else hidden”>

Our secret is being happy

</p>

<template> —> <ng-template>

使用示例

import { Component, OnInit } from ‘@angular/core’;

import { Observable } from ‘rxjs/Observable’;

import ‘rxjs/add/observable/of’;

import ‘rxjs/add/operator/delay’;

 

@Component({

selector: ‘exe-app’,

template: `

<ng-template #fetching>

<p>Fetching…</p>

</ng-template>

<p *ngIf=”auth | async; else fetching; let user”>

{{user.username }}

</p>

`,

})

export class AppComponent implements OnInit {

auth: Observable<{}>;

ngOnInit() {

this.auth = Observable

.of({ username: ‘semlinker’, password: ‘segmentfault’ })

.delay(new Date(Date.now() + 2000));

}

}

 

使用 [hidden] 属性控制元素可见性存在的问题

<div [hidden]=”!showGreeting”>

Hello, there!

</div>

上面的代码在通常情况下,都能正常工作。但当在对应的 DOM 元素上设置 display: flex 属性时,尽管[hidden] 对应的表达式为 true,但元素却能正常显示。对于这种特殊情况,则推荐使用 *ngIf。

直接使用 DOM API 获取页面上的元素存在的问题

@Component({

selector: ‘my-comp’,

template: `

<input type=”text” />

<div> Some other content </div>

`

})

export class MyComp {

constructor(el: ElementRef) {

el.nativeElement.querySelector(‘input’).focus();

}

}

以上的代码直接通过 querySelector() 获取页面中的元素,通常不推荐使用这种方式。更好的方案是使用 @ViewChild 和模板变量,具体示例如下:

@Component({

selector: ‘my-comp’,

template: `

<input #myInput type=”text” />

<div> Some other content </div>

`

})

export class MyComp implements AfterViewInit {

@ViewChild(‘myInput’) input: ElementRef;

constructor(private renderer: Renderer) {}

ngAfterViewInit() {

this.renderer.invokeElementMethod(

this.input.nativeElement, ‘focus’);

}

}

另外值得注意的是,@ViewChild() 属性装饰器,还支持设置返回对象的类型,具体使用方式如下:

@ViewChild(‘myInput’) myInput1: ElementRef;

@ViewChild(‘myInput’, {read: ViewContainerRef}) myInput2: ViewContainerRef;

若未设置 read 属性,则默认返回的是 ElementRef 对象实例。

 

第六节 – 事件绑定

在 Angular 中,我们可以通过 (eventName) 的语法,实现事件绑定。

基础知识

事件绑定语法

<date-picker (dateChanged)=”statement()”></date-picker>

等价于

<date-picker on-dateChanged=”statement()”></date-picker>

介绍完事件绑定的语法,接下来我们来为第五节中的 UserComponent 组件,开发一个功能,即可以让用户动态控制技能信息的显示与隐藏。

事件绑定示例

@Component({

selector: ‘sl-user’,

template: `

<button (click)=”toggleSkills()”>

{{ showSkills ? “隐藏技能” : “显示技能” }}

</button>

`

})export class UserComponent {

// …

toggleSkills() {

this.showSkills = !this.showSkills;

}

}

第七节 – 表单模块简介

Angular 中有两种表单:

Template Driven Forms – 模板驱动式表单 (类似于 AngularJS 1.x 中的表单 )

Reactive Forms – 响应式表单

本小节主要介绍模板驱动式的表单,接下来我们来演示如何通过表单来为我们的之前创建的 UserComponent 组件,增加让用户自定义技能的功能。

基础知识

导入表单模块

import { FormsModule } from ‘@angular/forms’;// …@NgModule({

imports: [BrowserModule, FormsModule],

declarations: [AppComponent, UserComponent],

bootstrap: [AppComponent]

})export class AppModule { }

模板变量语法

<video #player></video>

<button (click)=”player.pause()”>Pause</button>

等价于

<video ref-player></video>

表单使用示例

@Component({

selector: ‘sl-user’,

template: `

<div *ngIf=”showSkills”>

<h3>我的技能</h3>

<form (submit)=”addSkill(skill.value)”>

<label>添加技能</label>

<input type=”text” #skill>

</form>

</div>

`

})export class UserComponent {

// …

addSkill(skill: string) {

let skillStr = skill.trim();

if (this.skills.indexOf(skillStr) === -1) {

this.skills.push(skillStr);

}

}

}

第八节 – Http 模块简介

Angular 4.3 版本后,推荐使用 HttpClient,可以参考 Angular HTTP Client 快速入门

基础知识

导入 Http 模块

// … import { HttpModule } from ‘@angular/http’;

@NgModule({

imports: [BrowserModule, FormsModule, HttpModule],

declarations: [AppComponent, UserComponent],

bootstrap: [AppComponent]

})export class AppModule { }

使用 Http 服务步骤

(1) 从 @angular/http 模块中导入 Http 类

(2) 导入 RxJS 中的 map 操作符

(3) 使用 DI 方式注入 http 服务

(4) 调用 http 服务的 get() 方法,设置请求地址并发送 HTTP 请求

(5) 调用 Response 对象的 json() 方法,把响应体转成 JSON 对象

(6) 把请求的结果,赋值给对应的属性

Http 服务使用示例

使用 Http 服务

import { Component, OnInit } from ‘@angular/core’;import { Http } from ‘@angular/http’; // (1)import ‘rxjs/add/operator/map’; // (2)

interface Member {

id: string;

login: string;

avatar_url: string;

}

@Component({

selector: ‘sl-members’,

template: `

<h3>Angular Orgs Members</h3>

<ul *ngIf=”members”>

<li *ngFor=”let member of members;”>

<p>

<img [src]=”member.avatar_url” width=”48″ height=”48″/>

ID:<span>{{member.id}}</span>

Name: <span>{{member.login}}</span>

</p>

</li>

</ul>

`

})export class MembersComponent implements OnInit {

members: Member[];

 

constructor(private http: Http) { } // (3)

 

ngOnInit() {

this.http.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`) // (4)

.map(res => res.json()) // (5)

.subscribe(data => {

if (data) this.members = data; // (6)

});

}

}

声明 MembersComponent 组件

// …import { MembersComponent } from ‘./members.component’;

@NgModule({

imports: [BrowserModule, FormsModule, HttpModule],

declarations: [AppComponent, UserComponent, MembersComponent],

bootstrap: [AppComponent]

})export class AppModule { }

使用 MembersComponent 组件

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `

<sl-members></sl-members>

`,

})export class AppComponent {}

第九节 – 注入服务

基础知识

组件中注入服务步骤

(1) 配置已创建的服务,如:

@NgModule({

// …

providers: [MemberService]

})export class AppModule { }

(2) 导入已创建的服务,如:

import { MemberService } from ‘../member.service’;

(3) 使用构造注入方式,注入服务:

export class MembersComponent implements OnInit {

// …

constructor(private memberService: MemberService) { }

}

服务使用示例

创建 MemberService 服务

import { Injectable } from ‘@angular/core’;import { Http } from ‘@angular/http’;

@Injectable()export class MemberService {

constructor(private http: Http) { }

 

getMembers() {

return this.http

.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)

.map(res => res.json())

}

}

配置 MemberService 服务

import { MemberService } from “./member.service”;

@NgModule({

// …

providers:[MemberService],

bootstrap: [AppComponent]

})export class AppModule { }

使用 MemberService 服务

// …import { MemberService } from “./member.service”;

@Component({…})export class MembersComponent implements OnInit {

members: Member[];

 

constructor(private memberService: MemberService) { }

 

ngOnInit() {

this.memberService.getMembers()

.subscribe(data => {

if (data) this.members = data;

});

}

}

第十节 – 路由模块简介

基础知识

导入路由模块

// …import { RouterModule } from ‘@angular/router’;

@NgModule({

imports: [BrowserModule, FormsModule, HttpModule, RouterModule],

declarations: [AppComponent, UserComponent, MembersComponent],

bootstrap: [AppComponent]

})export class AppModule { }

配置路由信息

import { Routes, RouterModule } from ‘@angular/router’;import { UserComponent } from ‘./user.component’;

export const ROUTES: Routes = [

{ path: ‘user’, component: UserComponent }

];

@NgModule({

imports: [

BrowserModule,

RouterModule.forRoot(ROUTES)

],

// …

})export class AppModule {}

routerLink 指令

为了让我们链接到已设置的路由,我们需要使用 routerLink 指令,具体示例如下:

<nav>

<a routerLink=”/”>首页</a>

<a routerLink=”/user”>我的</a></nav>

当我们点击以上的任意链接时,页面不会被重新加载。反之,我们的路径将在 URL 地址栏中显示,随后进行后续视图更新,以匹配 routerLink 中设置的值。

router-outlet 指令

该指令用于告诉 Angular 在哪里加载组件,当 Angular 路由匹配到响应路径,并成功找到需要加载的组件时,它将动态创建对应的组件,并将其作为兄弟元素,插入到 router-outlet 元素中。具体示例如下:

@Component({

selector: ‘app-root’,

template: `

<div class=”app”>

<h3>Our app</h3>

<router-outlet></router-outlet>

</div>

`

})export class AppComponent {}

路由使用示例

配置路由信息

export const ROUTES: Routes = [

{ path: ”, pathMatch: ‘full’, redirectTo: ‘user’ },

{ path: ‘user’, component: UserComponent },

{ path: ‘members’, component: MembersComponent }

];

@NgModule({

imports: [BrowserModule, FormsModule, HttpModule,

RouterModule.forRoot(ROUTES)],

// …

})export class AppModule { }

配置路由导航

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `

<div class=”app”>

<h1>欢迎来到Angular的世界</h1>

<nav>

<a routerLink=”/user”>我的</a>

<a routerLink=”/members”>Angular成员</a>

</nav>

<router-outlet></router-outlet>

</div>

`,

})export class AppComponent { }

完整示例

AppModule

import { NgModule } from ‘@angular/core’;

import { BrowserModule } from ‘@angular/platform-browser’;

import { FormsModule } from ‘@angular/forms’;

import { HttpModule } from ‘@angular/http’;

import { RouterModule, Routes } from ‘@angular/router’;

import { AppComponent } from ‘./app.component’;

import { UserComponent } from ‘./user.component’;

import { MembersComponent } from ‘./members.component’;

import { MemberService } from “./member.service”;

export const ROUTES: Routes = [

{ path: ”, pathMatch: ‘full’, redirectTo: ‘user’ },

{ path: ‘user’, component: UserComponent },

{ path: ‘members’, component: MembersComponent }

];

@NgModule({

imports: [BrowserModule, FormsModule, HttpModule,

RouterModule.forRoot(ROUTES)],

declarations: [AppComponent, UserComponent, MembersComponent],

providers: [MemberService],

bootstrap: [AppComponent]

})export class AppModule { }

AppComponent

import { Component } from ‘@angular/core’;

@Component({

selector: ‘my-app’,

template: `

<div class=”app”>

<h1>欢迎来到Angular的世界</h1>

<nav>

<a routerLink=”/user”>我的</a>

<a routerLink=”/members”>Angular成员</a>

</nav>

<router-outlet></router-outlet>

</div>

`,

})export class AppComponent { }

UserComponent

import { Component } from ‘@angular/core’;

 

interface Address {

province: string;

city: string;

}

@Component({

selector: ‘sl-user’,

template: `

<h2>大家好,我是{{name}}</h2>

<p>我来自<strong>{{address.province}}</strong>省,

<strong>{{address.city}}</strong>市

</p>

<button (click)=”toggleSkills()”>

{{ showSkills ? “隐藏技能” : “显示技能” }}

</button>

<div *ngIf=”showSkills”>

<h3>我的技能</h3>

<ul>

<li *ngFor=”let skill of skills”>

{{skill}}

</li>

</ul>

<form (submit)=”addSkill(skill.value)”>

<label>添加技能</label>

<input type=”text” #skill>

</form>

</div>

`

})export class UserComponent {

name: string;

address: Address;

showSkills: boolean;

skills: string[];

 

constructor() {

this.name = ‘Semlinker’;

this.address = {

province: ‘福建’,

city: ‘厦门’

};

this.showSkills = true;

this.skills = [‘AngularJS 1.x’, ‘Angular 2.x’, ‘Angular 4.x’];

}

 

toggleSkills() {

this.showSkills = !this.showSkills;

}

 

addSkill(skill: string) {

let skillStr = skill.trim();

if (this.skills.indexOf(skillStr) === -1) {

this.skills.push(skillStr);

}

}

}

MembersComponent

import { Component, OnInit } from ‘@angular/core’;import { Http } from ‘@angular/http’;import ‘rxjs/add/operator/map’;

import { MemberService } from “./member.service”;

interface Member {

id: string;

login: string;

avatar_url: string;

}

@Component({

selector: ‘sl-members’,

template: `

<h3>Angular Orgs Members</h3>

<ul *ngIf=”members”>

<li *ngFor=”let member of members;”>

<p>

<img [src]=”member.avatar_url” width=”48″ height=”48″/>

ID:<span>{{member.id}}</span>

Name: <span>{{member.login}}</span>

</p>

</li>

</ul>

`

})export class MembersComponent implements OnInit {

members: Member[];

 

constructor(private memberService: MemberService) { }

 

ngOnInit() {

this.memberService.getMembers()

.subscribe(data => {

if (data) this.members = data;

});

}

}

MemberService

import { Injectable } from ‘@angular/core’;import { Http } from ‘@angular/http’;

@Injectable()export class MemberService {

constructor(private http: Http) { }

getMembers() {

return this.http

.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)

.map(res => res.json())

}

}

 

打赏

未经允许不得转载:五二零九 » Angular4 中文文档

赞 (4)
分享到:更多 ()