Description
安装
基于 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
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实际项目中,最常用的指令是ngIf
和ngFor
指令
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
用于多个条件分支的情况,配合ngSwitchCase
和ngSwitchDefault
两个指令实现不同的视图切换
<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>
引入样式和脚本
局部
局部样式可以配合styleUrls
和styles
进行引入
@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": [],