Angular6 學習筆記——組件詳解之組件通訊


angular6.x系列的學習筆記記錄,仍在不斷完善中,學習地址:

https://www.angular.cn/guide/template-syntax

http://www.ngfans.net/topic/12/post/2

 

系列目錄

(1)組件詳解之模板語法

(2)組件詳解之組件通訊

(3)內容投影, ViewChild和ContentChild

(4)指令

(5)路由

 

目錄章節

 1 前言

 2 Angular組件間的通訊

   2.1 父子組件間的通訊

     2.1.1 父組件設置子組件屬性

     2.1.2 父組件調用子組件事件

     2.1.3 子組件向父組件發射事件

   2.2 非父子組件通訊

     2.2.1 Service

     2.2.2 路由傳值

       2.2.2.1 傳遞一個值

       2.2.2.2 傳遞一個對象

 3 通用方式實現通訊

   3.1 localStorage

   3.2 服務端

  

1前言

前端框架,例如extjs,vue,angular等,都是或趨於組件化,所以組件間的通訊,是一個亟需解決的問題

一般而且言,這些組件之間都會形成這種樹形結構

               圖片來源:大漠窮秋

組件之間會有下列3種關系:

1父子關系

2兄弟關系

3沒有直接關系

 

通常采用下列方式處理(某些方式是框架特有)組件間的通訊,如下:

1父子組件之間的交互(@Input/@Output/模板變量/@ViewChild)

2非父子組件(Service/localStorage)

3還可以利用Session等服務器端的解決方法

 

2Angular組件間的通訊

2.1父子組件之間的通訊

在父子組件之間通訊:

 @Input:是屬性綁定,父組件向子組件傳遞數據

 @Output:是事件綁定,子組件向父組件傳遞數據的同時觸發事件

 

2.1.1在父組件設置子組件上面的的屬性

通過@input綁定子組件的屬性,注意屬性得是公開public的,私有private屬性是無法傳遞的

es6新語法get/set.為屬性提供了一個方便習慣的讀/寫方式, 攔截屬性的存取行為。

在父組件設置該屬性,就能夠通過set方法來修改,從而實現在父組件設置子組件屬性

代碼如下

1   <h1>{{childTitle}}</h1>
子組件模板文件
 1 import { Component, OnInit, Input } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-child',
 5   templateUrl: './child.component.html',
 6   styleUrls: ['./child.component.sass']
 7 })
 8 export class ChildComponent implements OnInit {
 9 
10   private _childTitle: string = '子組件標題';
11 
12   @Input()
13   set childTitle(childTitle: string) {
14     this._childTitle = childTitle;
15   }
16   get childTitle(): string {
17     return this._childTitle;
18   }
19 
20   constructor() { }
21 
22   ngOnInit() {
23 
24   }
25 }
子組件Ts文件
1 <p>
2   parent-and-child works!
3 </p>
4 <app-child childTitle="可設置子組件標題"></app-child>
父組件模板文件
 1 import { Component, OnInit } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-parent',
 5   templateUrl: './parent-and-child.component.html',
 6   styleUrls: ['./parent-and-child.component.sass']
 7 })
 8 export class ParentAndChildComponent implements OnInit {
 9 
10   constructor() { }
11 
12   ngOnInit() {
13 
14   }
15 
16 }
父組件Ts文件

 

2.1.2父組件直接調用子組件的方法

通過模板內部定義子組件變量,在父組件上可以直接調用子組件的方法,如下:

1 <p>child work</p>
子組件模板文件
 1 import { Component, OnInit, Input } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-child',
 5   templateUrl: './child.component.html',
 6   styleUrls: ['./child.component.sass']
 7 })
 8 export class ChildComponent implements OnInit {
 9   constructor() { }
10 
11   ngOnInit() {
12 
13   }
14 
15   childPrint() {
16     alert("來自子組件的打印");
17   }
18 }
子組件Ts文件
1 <p>
2   parent-and-child works!
3 </p>
4 <app-child #child></app-child>
5 <button (click)="child.childPrint()"></button>
父組件模板文件
 1 import { Component, OnInit } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-parent',
 5   templateUrl: './parent-and-child.component.html',
 6   styleUrls: ['./parent-and-child.component.sass']
 7 })
 8 export class ParentAndChildComponent implements OnInit {
 9 
10   constructor() { }
11 
12   ngOnInit() {
13 
14   }
15 
16 }
父組件Ts文件

 

2.1.3父組件接受子組件派發的事件

通過@Output在子組件綁定一個事件發射器,在父組件通過事件綁定監聽該事件

這樣在子組件派發一個事件,父組件就能夠收到

1 <p>child work</p>
子組件模板文件
 1 import { Component, OnInit, Output, EventEmitter } from '@angular/core';
 2 
 3 
 4 @Component({
 5   selector: 'app-child',
 6   templateUrl: './child.component.html',
 7   styleUrls: ['./child.component.sass']
 8 })
 9 export class ChildComponent implements OnInit {
10 
11   @Output()
12   initEmit = new EventEmitter<string>();
13 
14   constructor() { }
15 
16   ngOnInit() {
17     this.initEmit.emit("子組件初始化成功");
18   }
19 }
子組件TS文件
1 <p>
2   parent-and-child works!
3 </p>
4 <app-child (initEmit)="accept($event)"></app-child>
父組件模板文件
 1 import { Component, OnInit, Output, EventEmitter } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-parent',
 5   templateUrl: './parent-and-child.component.html',
 6   styleUrls: ['./parent-and-child.component.sass']
 7 })
 8 export class ParentAndChildComponent implements OnInit {
 9 
10   constructor() { }
11 
12   ngOnInit() {
13     
14   }
15   accept(msg:string) {
16     alert(msg);
17   }
18 }
父組件TS文件

 

2.2沒有直接關系的組件

2.2.1service

做一個全局單例的service,然后多個組件共享這個實例,當然就可以共享其中的成員,來進行通訊

                                   圖片來源:大漠窮秋

具體代碼如下

1 import { Component, Injectable, EventEmitter } from '@angular/core';
2 @Injectable()
3 export class myService {
4   public info:string = '';
5   constructor() {}
6 }
service文件

在app.module.ts文件的providers里添加這個服務

1 <p>child1 work</p>
2 
3 <button (click)="showInfo()"></button>
組件1的模板文件
 1 import { Component, OnInit} from '@angular/core';
 2 import { myService } from '../../../service/myService..service';
 3 
 4 
 5 @Component({
 6   selector: 'app-child',
 7   templateUrl: './child1.component.html',
 8   styleUrls: ['./child1.component.sass']
 9 })
10 export class Child1Component implements OnInit {
11 
12   constructor(
13     public service: myService
14   ) { }
15 
16   ngOnInit() {
17     
18   }
19   showInfo() {
20     alert(this.service.info);
21   }
22 }
組件1的TS文件
1 <p>
2   child2 works!
3 </p>
4 <button (click)="changeInfo()"></button>
組件2的模板文件
 1 import { Component, OnInit} from '@angular/core';
 2 import { myService } from '../../service/myService..service';
 3 
 4 @Component({
 5   selector: 'app-child2',
 6   templateUrl: './child2.component.html',
 7   styleUrls: ['./child2.component.sass']
 8 })
 9 export class Child2Component implements OnInit {
10 
11   constructor(
12     public service: myService
13   ) { }
14 
15   ngOnInit() {
16 
17   }
18   changeInfo() {
19     this.service.info = this.service.info + "1234";
20   }
21 }
組件2的TS文件

 

2.2.2路由傳值

對於2個不同路由的組件,我們也可以通過路由傳遞信息

假設2個路由分別為~/home,~/about

補充下述代碼路由的引用

1 import { Router } from '@angular/router';
2 import { ActivatedRoute, Params } from '@angular/router';
3 
4   constructor(
5     private router: Router,
6     private route: ActivatedRoute,
7   ) { }

 

2.2.2.1傳遞一個值

 假如從~/home路由向~/about路由傳遞一個字符串或數字

 1先把~/about的路由地址改為~/about/:id, (:id 是一個路由參數的令牌(Token),比如~/home/42 這個URL中,“42”就是id參數的值)

 2在/home寫上路由跳轉且傳值的連接

1 <button [routerLink]="['/about',1]">跳轉</button>
2 <button [routerLink]="['/about',"home"]">跳轉</button>

 3在跳至的頁面~/about接受傳入的值

1   id: string = '';
2 
3   ngOnInit() {
4     //獲取傳入的值
5     this.id = this.route.snapshot.params['id'];
6   }

 

2.2.2.2傳遞一個對象

類似於上述的傳遞一個值,但是不需要再路由末尾加上/:id

代碼也有些不同

1       this.router.navigate(['/about'], {
2         queryParams: {
3           id: '1',
4           status: true
5         }
6       });

接受傳入的對象

1   id: number = 0;
2   status: boolean = false;
3   ngOnInit() {
4     this.route.queryParams
5       .subscribe((params: Params) => {
6         this.id = params['id'];
7         this.status = params['status'];
8       })
9   }

 

3通用方式實現通訊

3.1localstorage處理

在angular中也可以使用本地存儲這種比較通用的方式在組件間通訊,但本地存儲有下列弊端:

1存儲空間有限

2只能存儲字符串

                                       圖片來源:大漠窮秋

具體的實現代碼如下

 1 import { Component, OnInit } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-child1',
 5   templateUrl: './child1.component.html',
 6   styleUrls: ['./child1.component.sass']
 7 })
 8 export class Child1Component implements OnInit {
 9 
10   constructor() { }
11 
12   ngOnInit() {
13 
14   }
15 
16    setData(){
17     window.localStorage.setItem("test", JSON.stringify({ key: 'test', value: 1 }));
18   }
19 }
組件1的Ts的文件
 1 import { Component, OnInit } from '@angular/core';
 2 
 3 @Component({
 4   selector: 'app-child2',
 5   templateUrl: './child2.component.html',
 6   styleUrls: ['./child2.component.sass']
 7 })
 8 export class Child2Component implements OnInit {
 9 
10   constructor() { }
11 
12   ngOnInit() {
13 
14   }
15 
16    getData() {
17     var json = window.localStorage.getItem("test");
18     var obj = JSON.parse(json);
19     console.log(obj.key);
20     console.log(obj.value);
21   }
22 }
23 
24 
25  
26 
27  
28 
29  
組件2的TS文件

 

3.2服務端處理

也可以在服務端來處理組件間的通訊問題,這是一個思路,但是已經脫離討論的主題,就不贅述

 (終)

 

文檔信息

 


感謝您的閱讀,如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕。本文歡迎各位轉載,但是轉載文章之后必須在文章頁面中給出作者和原文連接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM