Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

angular4 #35

Open
Wscats opened this issue Jul 11, 2017 · 0 comments
Open

angular4 #35

Wscats opened this issue Jul 11, 2017 · 0 comments

Comments

@Wscats
Copy link
Owner

Wscats commented Jul 11, 2017

安装

基于 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项目

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant