- 
                Notifications
    
You must be signed in to change notification settings  - Fork 125
 
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"
     *ngSwitchDefaultngSwitch用于多个条件分支的情况,配合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,引入带下划线_,带@符号[email protected]@weui才是真身,而非weui文件夹,那个是快捷方式,还有文件的路径是基于src文件的相对路径
"styles": [
        "styles.css",
        "../node_modules/[email protected]@weui/dist/style/weui.css"
],举一反三,全局引入JS也可以在.angular-cli.json文件中的引入
"scripts": [],