Skip to content

angular4 #35

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