Skip to content

angular4 #35

@Wscats

Description

@Wscats

安装

基于 Angular Quickstart,使用 Git 克隆 quickstart 项目,安装项目所需依赖并验证环境是否搭建成功

git clone https://github.com/angular/quickstart ng4-quickstart cd quickstart ng4-quickstart npm i npm start

定义组件

在app文件夹里面新建components文件夹,在里面新建user.component.ts

image

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: '广州'  };*/ //支持构造函数的形式初始化数据 name: string; address: any; constructor() { this.name = 'Wscats'; this.address = { province: '广东', city: '广州' } } }

声明组件

import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; //引入刚才新建的user.component文件 import { UserComponent } from './components/user.component'; @NgModule({ imports: [ BrowserModule ], //并在数组中注入UserComponent  declarations: [ AppComponent , UserComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }

使用组件

app.component.ts文件里面的template模板中添加<sl-user></sl-user>组件

import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Hello {{name}} Wscats</h1> <sl-user></sl-user> `, }) export class AppComponent { name = 'Angular'; }

接口

定义接口来判断对象的类型

import { Component } from '@angular/core'; //boolean string[] boolean string类型等 //必须写在@Component前面 interface Author { name: string; age: number; } @Component({ selector: 'ws-list', template: `  <ul> 	<li *ngFor="let p of people;">{{p}}</li>  </ul>  <p>{{author.name}}<p>  ` }) export class UserComponent { author: Author constructor() { this.author = { name: "Corrine",	age 666 } this.people = ["wscats", "oaoafly", "corrine"] } }

表达式

可以使用{{}}插值语法实现数据绑定

绑定普通文本

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: 'sl-user', template: `  <h2>大家好,我是{{name}}</h2>  <p>我来自<strong>{{address.province}}</strong>省,  <strong>{{address.city}}</strong>市  </p>  ` }) export class UserComponent { /*name = 'Semlinker'; address = {  province: '广东',  city: '广州' };*/ name: string; address: any; constructor() { this.name = 'Wscats'; this.address = { province: '广东', city: '广州' } } }

管道/过滤器

可以使用Angular内置的json管道,来显示对象信息

@Component({ selector: 'my-app', template: `  ...  <p>{{address | json}}</p>  `, }) export class AppComponent { name = 'Wscats'; address = { province: '广东', city: '广州' } }

常用指令

在Angular实际项目中,最常用的指令是ngIfngFor指令

ngFor

语法:

<li *ngFor="let item of items;">...</li>

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

import { Component } from '@angular/core'; @Component({ selector: 'ws-list', template: `  <ul> 	<li *ngFor="let p of people">{{p}}</li>  </ul>  ` }) export class UserComponent { constructor() { this.people = ["wscats","oaoafly","corrine"] } }

ngIf

语法:

//接受布尔值 <div *ngIf="condition">...</div>

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

import { Component } from '@angular/core'; @Component({ selector: 'ws-list', template: `  <ul *ngIf = "isShowList"> 	<li *ngFor="let p of people;"> 	<div *ngIf = "p.isShow">{{p.name}}</div> 	</li>  </ul>  ` }) export class UserComponent { constructor() { this.isShowList = true; this.people = [{ name: "Wscats", isShow: true }, { name: "Oaoafly", isShow: false }, { name: "Corrine", isShow: true }]; } }

ngClass

语法

[ngClass]="{'类名':boolean值}"

第一个参数为类名称,第二个参数为boolean值,如果为true就添加第一个参数的类,示例组件如下

import { Component } from '@angular/core'; @Component({ selector: 'header-cp', template: `  <h1 [ngClass]="{'red':bool}">header</h1>  <button (click)="testClick()">OK</button>  `, styles: [` 	.red{ 	color: red 	}  `] }) export class HeaderComponent { bool: boolean = true; testClick() { this.bool = !this.bool; } }

ngStyle

语法

[ngStyle]="{'css属性名':'css属性值'}"

注意驼峰和非驼峰写法均有效果

import { Component } from '@angular/core'; @Component({ selector: 'header-cp', template: `  //驼峰和非驼峰写法均可  <p [ngStyle]="{'backgroundColor':'green'}">header</p>  <p [ngStyle]="{'background-color':'green'}">header</p>  ` }) export class HeaderComponent {}

由于ngShow指令已经移除,所以我们可以用它来实现ngShow指令,就像下面代码一样

[ngStyle]="{'display': bool?'block':'none'}"

ngSwitch

语法

[ngSwitch]="变量" *ngSwitchCase="固值1" *ngSwitchCase="固值2" *ngSwitchDefault

ngSwitch用于多个条件分支的情况,配合ngSwitchCasengSwitchDefault两个指令实现不同的视图切换

<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>

ngNonBindable

有时候我们需要不要绑定页面的某个部分,使用了ngNonBindable,花括号就会被当做字符串一起显示出来

<div ngNonBindable> {{这里的内容不会被绑定}} </div>

innerHTML

输出html结构,比如配合富文本编辑器使用使用,这个指令会非常有用,但也需要注意有可能会遭受XSS攻击

import { Component } from '@angular/core'; //输出html结构必须引入DomSanitizer模块 import { DomSanitizer } from '@angular/platform-browser'; @Component({ selector: 'header-cp', template: ` <div [innerHTML]="html" ></div>  `, }) export class HeaderComponent { html: any; constructor(private sanitizer: DomSanitizer) { //如果不用DomSanitizer来转换,会出现警告,并且html结构不会完整显示 this.html = this.sanitizer.bypassSecurityTrustHtml("<p>要进行<span style='color: red'>转换的内容</span>~</p>"); } }

ngModel

必须在app.module.ts文件中引入FormsModule 模块,然后就可以在组件中使用ngModel指令

import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; // 使用ngModel必须引入FormsModule模块 import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ // 注入FormsModule imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }

组件中就可以使用ngModel进行数据绑定,记得一定要写上name属性,不然不会生效

import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `  <p>{{num}}</p>  <!---双向数据绑定->  <input name="num" type="number" [(ngModel)]="num" />  <!---单向数据绑定->  <input name="num" type="number" [ngModel]="num" />  <button (click)="ok()">ok</button>  `, }) export class AppComponent { num = 1; ok(){ this.num++ console.log("ok") } }

事件绑定

可以通过(eventName)的语法,实现事件绑定
语法:

<date-picker (dateChanged)="statement()"></date-picker> //等价于 <date-picker on-dateChanged="statement()"></date-picker>

下面我们就可以在页面上的按钮中绑定一个on-click事件

import { Component } from '@angular/core'; @Component({ selector: 'ws-event', template: `  <button (click)="toggleSkills()">  {{ showSkills ? "隐藏技能" : "显示技能" }}  </button>  ` }) export class EventComponent { toggleSkills() { this.showSkills = !this.showSkills; } }

Http模块

1.打开app.module.ts文件,从@angular/http模块中导入 Http 类,并在imports数组中注入HttpModule

import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpModule } from '@angular/http'; import { AppComponent } from './app.component'; import { UserComponent } from './components/user.component'; import { EventComponent } from './components/event.component'; @NgModule({ imports: [BrowserModule,HttpModule], declarations: [AppComponent, UserComponent, EventComponent], bootstrap: [AppComponent] }) export class AppModule {}

2.导入RxJS中的map操作符
3.使用DI方式注入http服务
4.调用http服务的get()方法,设置请求地址并发送HTTP请求
5.调用Response对象的json()方法,把响应体转成JSON对象
6.把请求的结果,赋值给对应的属性

import { Component } from '@angular/core'; import { Http } from '@angular/http'; // (1)步骤1 import 'rxjs/add/operator/map'; // (2)步骤2 导入RxJS中的map操作符 @Component({ selector: 'ws-event', template: ` ` }) export class EventComponent { constructor(private http: Http) {} //(3)步骤3 ngOnInit() { console.log(this); 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) }); } } }

服务

可以再app文件夹下面新建个service文件夹再创建data.service.ts,定义服务文件

export class DataService { getData() { return ['wscat', 'corrine', 'oaoafly']; } }

在app.module.ts文件里面的providers数组中注入DataService

import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { UserComponent } from './user.component'; //引入服务 import { DataService } from './service/data.service'; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent , UserComponent ], // 全局注入 providers: [ DataService ], bootstrap: [ AppComponent ] }) export class AppModule { }

加载data.service.ts文件,引入DataService服务,在constructor里面注入DataService服务,注意是private类型,并把方法命名为dataService在ng的ngOnInit生命周期内即可调用

import { Component } from '@angular/core'; import { DataService } from './service/data.service'; @Component({ selector: 'wscats', template: `  <h1>Hello {{name}}</h1>  `, }) export class UserComponent implements OnInit { constructor(private dataService: DataService) { } name = 'Angular'; // 生命周期 ngOnInit() { console.log("父组件ngOninit"); console.log(this.dataService.getData()) setTimeout(()=>{ this.name = "abc" },1000) } }

基于服务之间的组件通信

创建data.service.ts服务,并且在主模块中注入,里面的state默认为1

export class DataService { state:number; constructor(){ this.state = 1 } getData() { return ['wscat', 'corrine', 'oaoafly']; } }

父组件,触发DataService服务中state的改变

import { Component } from '@angular/core'; import { DataService } from '../../services/data.service'; @Component({ selector: ' wscats-cp', template: `  <!--子组件接受服务的改变-->  <test-cp></test-cp>  ` }) export class WscatsComponent { constructor(private dataService: DataService) { //父组件利用定时器去改变dataService服务中的的state值 setInterval(() => { this.dataService.state++ console.log(this.dataService) }, 1000) } }

子组件,监听DataService中state的变化并进行渲染

import { Component } from '@angular/core'; import { DataService } from '../../services/data.service'; @Component({ selector: 'test-cp', template: `  <!--这里就会观察到dataService的动态改变,从而完成父子之间的通信-->  <p>{{dataService.state}}</p>  ` }) export class TestComponent { //接受dataService并把它交给TestComponent的私有变量dataService constructor(private dataService: DataService) { } }

路由

需要引入@angular/router模块,当然要先在npm包管理中心下载

import { RouterModule } from '@angular/router';

路由器包含了多种服务RouterModule和多种指令RouterOutlet、RouterLink、RouterLinkActive
路由告诉路由器,当用户点击链接或者把URL粘贴到浏览器地址栏时,应该显示哪个视图,下面配置的意思为,当URL匹配到/home路由的时候,就在视图RouterOutlet上显示HomeComponent组件

... import { RouterModule } from '@angular/router'; ... // 省略code // 主模块 @NgModule({ // 内置服务 imports: [BrowserModule, RouterModule.forRoot([ { path: 'home', component: HomeComponent } ])], // 注册组件 declarations: [AppComponent, ...], // 自定义服务 providers: [...], // 注根组件 bootstrap: [AppComponent] }) export class AppModule { }

我们可以在根组件里,放router-outlet组件,这个相当于我们AngularJS的router-view标签,正如下面代码一样

import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `  <router-outlet></router-outlet>  `, }) export class AppComponent {}

当然我们还可以利用routerLink来进行路由的跳转

<a routerLink="/home">Heroes</a>

引入样式和脚本

局部

局部样式可以配合styleUrlsstyles进行引入

@Component({ selector: 'xpannel', templateUrl: './app.pannel.html', styleUrls: ['./app.pannel.css'], styles: [require("weui")] })

全局

全局样式可以在.angular-cli.json文件中引入,注意如果使用cnpm,引入带下划线_,带@符号_weui@1.1.2@weui才是真身,而非weui文件夹,那个是快捷方式,还有文件的路径是基于src文件的相对路径

"styles": [ "styles.css", "../node_modules/_weui@1.1.2@weui/dist/style/weui.css" ],

举一反三,全局引入JS也可以在.angular-cli.json文件中的引入

"scripts": [],

参考文档

Angular 4.x 修仙之路
Angular之路--带你来搭建Webpack 2 + Angular 4项目

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions