@Input() 和 @Output() 為子組件提供了一種與其父組件通信的方法。@Input() 允許父組件更新子組件中的數據。相反,@Output() 允許子組件向父組件發送數據。
父組件向子組件傳值—@Input子組件或指令中的 @Input() 裝飾器表示該屬性可以從其父組件中獲取值。
父組件 app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
msg = '你好,子組件';
}父組件 app.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<app-child [item]="msg"></app-child>
<router-outlet></router-outlet>子組件 child.component.ts
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
// 子組件或指令中的 @Input() 裝飾器表示該屬性可以從其父組件中獲取值。
@Input() item: string;
constructor() {
}
ngOnInit() {
}
}子組件 child.component.html
<p>父組件傳給子組件的值:{{item}}</p>
子組件向父組件傳值—@Output、EventEmitter子組件或指令中的 @Output() 裝飾器允許數據從子組件傳給父組件。子組件使用 @Output() 屬性來引發事件,以通知父組件這一變化。為了引發事件,@Output()必須是EventEmitter類型,它是@angular/core中用來發出自定義事件的類。
子組件 child.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
// 子組件或指令中的 @Input() 裝飾器表示該屬性可以從其父組件中獲取值。
@Input() item: string;
// 子組件或指令中的 @Output() 裝飾器允許數據從子組件傳給父組件。
@Output() newItemEvent = new EventEmitter<string>();
constructor() {
}
ngOnInit() {
}
addNewItem(value: string) {
console.log(value);
this.newItemEvent.emit(value);
}
}子組件 child.component.html
<p>父組件傳給子組件的值:{{item}}</p>
<label>Add an item: <input #newItem></label>
<button (click)="addNewItem(newItem.value)">子組件向父組件中添加item</button>父組件 app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
msg = '你好,子組件';
items = ['item1','item2', 'item3', 'item4'];
addItem(newItem: string) {
this.items.push(newItem);
}
}父組件 app.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<ul>
<li *ngFor="let item of items">{{item}}</li>
</ul>
<app-child [item]="msg" (newItemEvent)="addItem($event)"></app-child>
<router-outlet></router-outlet>
二、路由篇項目中使用路由要想在項目中使用路由,首先要創建一個帶路由的應用項目。通過指令ng new routing-app --routing可以創建一個附帶路由的項目。
1、為路由添加組件為了使用 Angular 的路由器,應用至少要有兩個組件才能從一個導航到另一個。要使用 CLI 創建組件,請在命令行輸入以下內容,其中 first 是組件的名稱:
ng generate component first為第二個組件重複這個步驟,但給它一個不同的名字。這裡的新名字是 second。
ng generate component secondCLI 會自動添加 Component 後綴,所以如果在編寫 first-component,那麼其組件名就是 FirstComponentComponent。
2、導入這些新組件要使用這些新組件,請把它們導入到該文件頂部的 AppRoutingModule 中,具體如下:
// 在app-routing.module.ts 文件中
import { FirstComponent } from './first/first.component';
import { SecondComponent } from './second/second.component';
3、定義一個基本路由創建路由有三個基本的構建塊。把 AppRoutingModule 導入 AppModule 並把它添加到 imports 數組中。Angular CLI 會為你執行這一步驟。但是,如果要手動創建應用或使用現存的非 CLI 應用,請驗證導入和配置是否正確。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module'; // CLI imports AppRoutingModule
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule // CLI adds AppRoutingModule to the AppModule's imports array
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }1、把 RouterModule 和 Routes 導入到你的路由模塊中。Angular CLI 會自動執行這一步驟。CLI 還為你的路由設置了Routes數組,並為@NgModule()配置了imports和exports數組。
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router'; // CLI imports router
const routes: Routes = []; // sets up routes constant where you define your routes
// configures NgModule imports and exports
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }2、在Routes數組中定義你的路由。這個數組中的每個路由都是一個包含兩個屬性的 JavaScript 對象。第一個屬性path定義了該路由的URL路徑。第二個屬性component定義了要讓 Angular 用作相應路徑的組件。
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
];3、最後把這些路由添加到你的應用中。現在你已經定義了路由,可以把它們添加到應用中了。首先,添加到這兩個組件的連結。把要添加路由的連結賦值給routerLink屬性。將屬性的值設置為該組件,以便在用戶點擊各個連結時顯示這個值。接下來,修改組件模板以包含<router-outlet>標籤。該元素會通知 Angular,你可以用所選路由的組件更新應用的視圖。
<!--app.component.html-->
<h1>Angular Router App</h1>
<!-- This nav gives you links to click, which tells the router which route to use (defined in the routes constant in AppRoutingModule) -->
<nav>
<ul>
<li><a routerLink="/first-component" routerLinkActive="active">First Component</a></li>
<li><a routerLink="/second-component" routerLinkActive="active">Second Component</a></li>
</ul>
</nav>
<!-- The routed views render in the <router-outlet>-->
<router-outlet></router-outlet>
路由順序路由的順序很重要,因為Router在匹配路由時使用「先到先得」策略,所以應該在不那麼具體的路由前面放置更具體的路由。首先列出靜態路徑的路由,然後是一個與默認路由匹配的空路徑路由。通配符路由是最後一個,因為它匹配每一個URL,只有當其它路由都沒有匹配時,Router才會選擇它。
設置通配符路由當用戶試圖導航到那些不存在的應用部件時,在正常的應用中應該能得到很好的處理。要在應用中添加此功能,需要設置通配符路由。當所請求的URL與任何路由器路徑都不匹配時,Angular路由器就會選擇這個路由。
要設置通配符路由,請在routes定義中添加以下代碼。
{ path: '**', component: PageNotFoundComponent }
設置重定向要設置重定向,請使用重定向源的path、要重定向目標的component和一個pathMatch值來配置路由,以告訴路由器該如何匹配URL。
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
{ path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
];
路由傳參1、動態路由1、首先在app-routing.module.ts文件中的routes數組中配置動態路由
{
path: 'first-component/:id',
component: FirstComponent,
}2、在html頁面中跳轉傳值
<!--動態路由傳值-->
<a routerLink="/first-component/3" routerLinkActive="active">First Component</a>
<!--或者-->
<a [routerLink]="['/first-component/',3]">First Component</a>
2、query形式傳參在html頁面中的routerLink的a標籤中直接傳參
<a routerLink="/second-component" [queryParams]="{name: '小笑殘虹'}" routerLinkActive="active">
Second Component
</a>
獲取路由參數信息1、獲取動態路由的值假如我要在FirstComponent組件中獲取動態路由傳遞的值,第一步:在first.component.ts文件中引入ActivatedRoute模塊,作為route注入到構造器函數中。
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-first',
templateUrl: './first.component.html',
styleUrls: ['./first.component.scss']
})
export class FirstComponent implements OnInit {
constructor(private route: ActivatedRoute) {
}
}然後就可以通過route.params.subscribe()方法獲取到傳遞的值了。
ngOnInit() {
// 獲取動態路由傳值
console.log(this.route.params);
this.route.params.subscribe(data => {
console.log(data);
this.id = data.id
})
}
2、獲取query形式傳遞過來的參數假如我要在SecondComponent組件中獲取query形式傳遞過來的值,第一步:在second.component.ts文件中引入ActivatedRoute模塊,作為route注入到構造器函數中。
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
@Component({
selector: 'app-second',
templateUrl: './second.component.html',
styleUrls: ['./second.component.scss']
})
export class SecondComponent implements OnInit {
constructor(
private route: ActivatedRoute,
) {
}
}然後就可以通過route.queryParams.subscribe()方法獲取到傳遞的值了。
ngOnInit() {
// 獲取params傳值
this.route.queryParams.subscribe(params => {
console.log(params);
this.name = params['name'];
});
}
js跳轉路由(編程式導航)我要在AppComponent組件中演示編程式導航,所以首先要在app.component.ts中引入Router模塊,並且在constructor函數中進行初始化,引入NavigationExtras模塊是為了進行query形式傳參,NavigationExtras模塊不需要在constructor構造器函數中初始化。
import { Router, NavigationExtras } from '@angular/router'
constructor(private router: Router) {}
1、js跳轉普通路由首先在頁面上定義一個按鈕用來模擬跳轉
<button (click)="goHome()">js跳轉路由</button>通過router.navigate()方法進行跳轉
// js跳轉普通路由
goHome() {
this.router.navigate(['/home'])
}
2、js跳轉動態路由<!-- js動態路由跳轉 -->
<button (click)="goToPath()">js動態路由跳轉</button>通過router.navigate()方法進行跳轉
// js跳轉動態路由
goToPath() {
// 路由跳轉 適合普通路由和動態路由
this.router.navigate(['/first-component/', '123'])
}
3、js跳轉路由query形式傳參注意:需要引入NavigationExtras模塊
<button (click)="queryRoute()">js跳轉路由query傳參</button>通過router.navigate()方法進行跳轉
// js跳轉路由query傳參 (get傳值)
queryRoute() {
let queryParams: NavigationExtras = {
queryParams: {
name: '王者榮耀'
}
}
this.router.navigate(['/second-component'], queryParams);
}
嵌套路由隨著你的應用變得越來越複雜,你可能要創建一些根組件之外的相對路由。這些嵌套路由類型稱為子路由。這意味著你要為你的應用添加第二,因為它是AppComponent之外的另一個<router-outlet>。
在這個例子中,還有兩個子組件,child-a和child-b。這裡的FirstComponent有它自己的<nav>和AppComponent之外的第二<router-outlet>。
<h2>First Component</h2>
<nav>
<ul>
<li><a routerLink="child-a">Child A</a></li>
<li><a routerLink="child-b">Child B</a></li>
</ul>
</nav>
<router-outlet></router-outlet>子路由和其它路由一樣,同時需要 path 和 component。唯一的區別是你要把子路由放在父路由的 children 數組中。
const routes: Routes = [
{
path: 'first-component',
component: FirstComponent, // this is the component with the <router-outlet> in the template
children: [
{
path: 'child-a', // child route path
component: ChildAComponent, // child route component that the router renders
},
{
path: 'child-b',
component: ChildBComponent, // another child route component that the router renders
},
],
},
];
HTTP客戶端篇使用HTTP與後端服務進行通信。大多數前端應用都要通過HTTP協議與伺服器通訊,才能下載或上傳數據並訪問其它後端服務。Angular 給應用提供了一個簡化的HTTP客戶端 API,也就是@angular/common/http中的HttpClient服務類。
HTTP客戶端服務提供了以下主要功能。
伺服器通訊的準備工作1、要想使用HttpClient,就要先在app.module.ts中導入Angular的HttpClientModule。大多數應用都會在根模塊AppModule中導入它。
// app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
// import HttpClientModule after BrowserModule.
HttpClientModule,
],
declarations: [
AppComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule {}2、在用到的地方引入HttpClient並在構造器函數中聲明。(我將要在NewsComponent組件中使用,所以在news.component.ts中引入HttpClient並在構造器函數中聲明)
// news.component.ts
import {HttpClient} from "@angular/common/http";
constructor(public http:HttpClient) { }
get 請求數據1、在news.component.html文件中定義一個按鈕,來實現get方法請求伺服器數據。
<button (click)="getData()">get請求</button>2、在news.component.ts文件中實現getData()方法,get請求接口可以使用開源的https:httpbin.org/get
// get請求
getData() {
// https:httpbin.org/get
// https://httpbin.org/post
let api = 'http://a.itying.com/api/productlist';
this.http.get(api).subscribe((res: any) => {
console.log(res);
this.list = res.result;
})
}
post 提交數據Angular5.x 以後get、post和伺服器交互使用的是HttpClientModule模塊。
1、在app.module.ts中引入HttpClientModule並注入
import {HttpClientModule} from '@angular/common/http';
imports: [ BrowserModule, HttpClientModule ]2、在用到的地方引入HttpClient、HttpHeaders模塊並在構造器函數中聲明HttpClient。
在news.component.html文件中定義一個按鈕,來實現post請求伺服器數據。
<button (click)="doLogin()">post提交數據</button>2、在news.component.ts文件中實現doLogin()方法,post請求接口可以使用開源的https:httpbin.org/post。
// post請求
doLogin() {
const httpOptions = {
headers: new HttpHeaders({"content-type": 'application/json'})
};
let url = 'https://httpbin.org/post';
this.http.post(url, {name: '小笑殘虹', age: 18}, httpOptions).subscribe((res: any) => {
console.log(res);
this.postDate = res.json;
})
}
Jsonp 請求數據1、在app.module.ts中引入HttpClientModule、HttpClientJsonpModule 並注入。
import {HttpClientModule,HttpClientJsonpModule} from '@angular/common/http';
imports: [ BrowserModule, HttpClientModule, HttpClientJsonpModule ]2、在用到的地方引入HttpClient並在構造函數聲明。
// news.component.ts
import {HttpClient} from "@angular/common/http";
constructor(public http:HttpClient) { }<button (click)="getJsonp()">jsonp處理跨域</button>// jsonp 跨域請求
getJsonp() {
/*
* http://a.itying.com/api/productlist?callback=xxx
* http://a.itying.com/api/productlist?cb=xxx
* */
let api = 'http://a.itying.com/api/productlist';
this.http.jsonp(api, 'callback').subscribe((res: any) => {
console.log(res);
this.list = res.result;
})
}
Angular 中使用第三方模塊 axios 請求數據1、安裝 axios
npm install axios --save2、用到的地方引入 axios
import axios from 'axios';3、看axios文檔使用
axios.get('/user?ID=12345')
.then(function (response){
// handle success console.log(response);
}).catch(function (error) {
// handle error console.log(error);
}).then(function () {
// always executed
});下面,我們創建一個HttpService來使用axios,在這裡可以對axios進行一些封裝。
// service/http-service.service.ts
import {Injectable} from '@angular/core';
import axios from 'axios';
@Injectable({
providedIn: 'root'
})
export class HttpServiceService {
constructor() {
}
axiosGet(api) {
return new Promise((resolve, reject) => {
axios.get(api)
.then(res => {
resolve(res);
})
})
}
}然後在app.module.ts中引入HttpServiceService服務並注入到providers數組中。
// app.module.ts
// 引入服務
import {HttpServiceService} from './service/http-service.service';
// 注入服務
providers: [HttpServiceService],之後在NewsComponent組件中使用HttpServiceService服務
// news.component.ts
// 引入服務
import {HttpServiceService} from '../service/http-service.service'
// 初始化
constructor(public httpService: HttpServiceService) {}<!--news.component.html-->
<button (click)="axiosGetData()">通過axios獲取數據</button>// news.component.ts
// axios get方法獲取數據
axiosGetData() {
let api = 'http://a.itying.com/api/productlist';
this.httpService.axiosGet(api).then((res: any) => {
console.log(res);
this.list = res.data.result;
})
}