Angular組件之間的交互

来源:http://www.cnblogs.com/nangxi/archive/2017/10/06/7630579.html
-Advertisement-
Play Games

這篇文章的題材相信已經有很多人寫過,如果你對Angular組件之間的交互瞭如指掌的話,那麼麻煩各位大神多多指教,如果你對Angular組件之間的交互一知半解,或者全然不知,那麼相信這篇文章對一些代碼的解讀對你會有所幫助! ...


Angular組件之間的交互分為:

1.通過輸入型綁定把數據從父組件傳到子組件。

2.通過setter截聽輸入屬性值的變化

3.通過ngOnChanges()來截聽輸入屬性值的變化

4.父組件監聽子組件的事件

5.父組件與子組件通過本地變數互動

6.父組件調用@ViewChild()

7.父組件和子組件通過服務來通訊

這些在Angular的中文官方文檔都有,類似的博客一大堆,寫這篇博客的目的不是說把人家做過的東西再做一遍,而是把人家做過的東西轉化成自己的東西,這樣才是有用的。

在博客正式開始之前我們先介紹一下項目目錄

----------app.component.ts

----------app.component.html

----------app.component.css

----------app.module.ts

----------child(文件夾)

--------------child.component.ts

--------------child.component.html

--------------child.component.css

一、通過輸入型綁定把數據從父組件傳到子組件

這個通訊方法的操作很簡單,父組件發送自己的數據給子組件,子組件接收父組件傳遞過來的數據。 1.app.component.html
<child [childData]="appData"></child><!--childData是子組件的接收參數,appData是父組件傳遞的數據,整個數據傳遞過程的重點,橋梁-->
2.app.component.ts
import { Component } from '@angular/core';
import { ChildComponent } from './child/child.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  appData=['Apple','Banana','watermelon','pear'];
}
3.child.component.ts
import { Component,Input } from '@angular/core';//記得導入Input裝飾器

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  title = 'child';
  @Input() childData:any;//接收數據的介面
}
4.child.component.html
<ul>
    <li *ngFor="let children of childData; let num1 = index">{{num1}}--{{children}}</li>
</ul>
<ul>
    <li *ngFor="let children of childData; index as num2">{{num2}}--{{children}}</li><!--index的第二種寫法-->
</ul>
我們第一個實驗將父組件的數組傳遞給子組件然後渲染出來,效果是這樣的

二、通過setter截聽輸入屬性值的變化

這種交互方式的書寫格式有些不太符合我們平時的書寫規範 1.app.component.html
<child *ngFor="let app of appData" [child]="app"></child>
2.app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  appData=['Apple','Banana',' ','pear']; //父組件數據
}
3.child.component.ts
import { Component,Input } from '@angular/core';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent {
  title = 'child';
  private _name = ''; //定義一個私有向量,來暫時儲存父組件傳遞過來的數據
  @Input() set child(name: string) { //child是我們用來接收父組件傳遞過來的數據的一個變數,我們用setter來截取到這個變數,然後做一些修改,child這個變數名
                                       //它是取決於父組件app.component.html裡面的[child]="app",不能隨便改動,child的形參名字可以隨便修改
    this._name = name.trim() || 'Oranges'; //會trim掉名字里的空格,並把空值替換成Oranges。
  }
 
  get child(): string{ //用get重新獲取重置過後的child變數,這個過程中_name這個是有變數就用到了
      return this._name;
  }
}
4.child.component.html
<p>{{child}}</p>
我們第二個實驗的效果是這樣的

三、通過ngOnChanges()來截聽輸入屬性值的變化

OnChanges是一個生命周期鉤子,一旦檢測到該組件(或指令)的輸入屬性發生了變化,Angular就會調用它的ngOnChanges()方法。 1.app.component.html
<table>
    <tr>
        <td>ID</td>
        <td><input type="text" [(ngModel)]="id"/></td>
    </tr>
    <tr>
        <td>PassWord</td>
        <td><input type="text" [(ngModel)]="password"/></td> <!--使用ngModel要記住在app.module.ts裡面添加FormsModule-->
    </tr>
    <tr colspan="2">
        <td><button (click)="reset()">Reset Log</button></td>
    </tr>
</table>
<div>
    <child [id]="id" [password]="password"></child>
</div>
2.app.component.ts
import { Component,ViewChild } from '@angular/core';//這裡使用了我們第六點將會用到的父組件調用@ViewChild(),第六點細講
import { ChildComponent } from './child/child.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title = 'app';
    id:number;
    password:number;
    @ViewChild(ChildComponent) childView: ChildComponent;//此處先忽略不看
    constructor() {
      this.reset();//構造函數,有初始化id和password的功能
    }

    reset() {
        this.id = 100001;
        this.password = 123456;
        if (this.childView) { 
            this.childView.reset(); 
        }
      }
}
3.child.component.ts
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnChanges {
  title = 'child';
  @Input() id: number;
  @Input() password: number;
  changeLog: string[] = []; //這個數組用來存放修改日誌,修改一個input就會儲存相應的記錄
  ngOnChanges(changes: SimpleChanges) {
      for (let propName in changes) {
          let chng = changes[propName];
          let cur  = JSON.stringify(chng.currentValue);//修改前的數據
          let prev = JSON.stringify(chng.previousValue);//修改後的數據
          this.changeLog.push(`${propName}被修改了: 前一個數據 = ${cur}, 後一個數據 = ${prev}`);
        }
    }
    reset() { 
      this.changeLog.length = 0; //清除日誌
    }
}
4.child.component.html
<div class="hero">
    <h4>-- Change Log --</h4>
    <div *ngFor="let chg of changeLog">{{chg}}</div> <!--將日誌一條一條列印出來-->
</div>
我們第三個實驗的效果是這樣的

四、父組件監聽子組件的事件

通過@Output裝飾器自定義一個方法,在需要emits(向上彈射)的函數裡面彈射變數 1.app.component.html
<p>{{title}}</p>
<child (onClick)="onCli($event)"></child> <!--onClick是子組件自定義的事件,觸發onClick事件,執行父組件的onCli()方法-->
2.app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title="你還沒點擊按鈕";
    onCli(isClick: boolean) { //父組件的方法,更換title的值
        if(isClick){ //如果子組件彈射出來的變數為true
            this.title="你點擊了按鈕"; //那麼就更改title
        } 
      }
}
3.child.component.ts
import { Component, EventEmitter, Output } from '@angular/core';//註意導入

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent{
  title = 'child';
  @Output() onClick = new EventEmitter<boolean>();//暴露自定義事件onClick
  click(isClick: boolean) { //click()只是一個普通的方法
    this.onClick.emit(isClick);//向父組件彈射isClick變數,這個變數在button被點擊的時候觸發
  }
}
4.child.component.html
<button (click)="click(true)">點擊</button> <!--給click方法傳入true-->
這種父子組件之間的通訊方式,需要註意以下幾點: 1.在子組件裡面定義並暴露出自定義事件; 2.在子組件裡面需要彈射的函數裡面彈射變數; 3.在父組件裡面通過$event接收變數。 我們第四個實驗的效果是這樣的

五、父組件與子組件通過本地變數互動

這種通訊比較簡單,而且父組件可以同時調用子組件的變數或方法
1.app.component.html
<p>{{title}}</p><!--調用父組件自己的變數-->
<p>{{data.title}}</p><!--調用子組件的變數-->
<child #data></child><!--在父組件模板里,新建一個本地變數來代表子組件,然後利用這個變數來讀取子組件的屬性和調用子組件的方法-->
<button (click)="data.click()">點擊</button><!--調用子組件的方法-->

2.app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title="app";//父組件的變數
}
3.child.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent{
  title = 'child';//子組件的變數
  click(){//子組件的方法
      this.title="changeChild";
  }
}
child.component.html不用編寫代碼 我們第五個實驗的效果是這樣的

六、父組件調用@ViewChild()

這種父子組件之間的通訊方式也很容易理解,項目代碼和第五個通訊方式差不多 1.app.component.html
<p>{{title}}</p>
<p>{{data.title}}</p>
<child #data></child>
<button (click)="onclick()">點擊</button><!--註意這裡,跟第五個方法有些區別-->
2.app.component.ts
import { Component } from '@angular/core';
import { ViewChild } from '@angular/core';
import { ChildComponent } from './child/child.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title="app";
    @ViewChild(ChildComponent)//通過@ViewChild屬性裝飾器,將子組件CountdownTimerComponent註入到私有屬性timerComponent裡面,此處不能加分號。
    private child: ChildComponent;
    onclick(){
        this.child.click();
    }
}
3.child.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent{
  title = 'child';
  click(){
      this.title="changeChild";
  }
}
child.component.html也是不用編寫代碼,我們第六個實驗的效果跟第五個是一樣的,這裡不再講述。

七、父組件和子組件通過服務來通訊

這種服務通訊方式我在一篇文章有詳細地解析過。這個實驗要在app.component.html加入新的文件Service.ts 1.app.component.html
<p>{{title}}</p>
<button (click)="onclick()">點擊</button>
<child></child>
2.app.component.ts
import { Component } from '@angular/core';
import { ChildComponent } from './child/child.component';
import { Service } from './Service';//導入服務

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    title='app';
    constructor(public pService: Service) { //原來的寫法是這樣的pService = new Service();
     }
    onclick(){
        this.title = this.pService.getData();
        console.log(this.title);
    }
}
3.child.component.ts
import { Component } from '@angular/core';
import { Service } from '../Service';

@Component({
  selector: 'child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.css']
})
export class ChildComponent{
  title = 'child';
  constructor(public pService: Service) {
    }
  onclick(){
    this.title = this.pService.getData();
  }
}
4.child.component.html
<p>{{title}}</p>
<button (click)="onclick()">點擊</button>
app.component.html和child.component.html,app.component.ts和child.component.ts的代碼幾乎一樣,目的是要展示出服務在父子組件甚至任何組件裡面的使用 5.Service.ts
import {Injectable} from "@angular/core"

@Injectable()
export class Service {
  title='service';//公共變數
  getData() {//公共方法
    return this.title;
  }
}
6.app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { ChildComponent } from './child/child.component';
import { Service } from './Service';//導入服務

@NgModule({
  declarations: [
    AppComponent,
    ChildComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [Service],//註冊服務
  bootstrap: [AppComponent]
})
export class AppModule { }
實驗七的效果是這樣的,在點擊之前 點擊之後

八、結語

至此七種父子組件之間的交互方式解析完畢,大家在不同的代碼情況因地制宜,選擇最合適的方式!












 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 表示一個作用於某對象結構中的各元素的操作。它使你可以在不改變各元素類的前提下定義作用於這些元素的新操作。 UML類圖: 具體代碼: 模塊說明:Visitor:抽象類或者介面,聲明visit方法中的參數定義哪些對象是可以被訪問的。ConcreteVisitor:具體訪問者實現的對象,實現被添加 ...
  • 1.2 服務治理和架構 我在矽谷那段時間,每天早上都單獨要一份omelet,就是美式煎蛋。2個雞蛋和黃油是必選的,另外需要自己在需要放的材料上打鉤,有多種芝士可選,另外還可以勾選洋蔥,蘑菇,培根,西蘭花等。 回國之後,經常也會自己這樣做早餐,只是總會在擺盤時,用圓火腿斜切兩片,然後將這這個片再四六分 ...
  • 您正工作於大型複雜的單體應用程式上,這是相當不錯的機會。您開發和部署應用程式的日常經歷是緩慢而痛苦的。微服務似乎是一個遙不可及的天堂。幸運的是,有一些戰略可以用來逃離單體地獄。在本文中,我將描述如何將單體應用程式逐漸重構為一組微服務。 ...
  • 本來應一個可愛帥氣的編輯之邀,要寫一本書《靜兒的互聯網服務治理私房菜》。想選服務治理的題材,想急著簽協議就寫了一個很匆忙的目錄和例章。寫書本是計划了很久的一件事情。現在反而有些猶豫了。我是不是應該把腳步放慢一些,再穩一些。我是不是應該自己先寫了一部分,再考慮簽約出版的事情。要做的事情太多了,比如:家 ...
  • 大部分網頁預設的背景色為白色,個人感覺比較刺眼,於是寫了個JS的腳本去改變body部分的背景色,代碼如下: 代碼比較簡單,直接創建了一個body上的css樣式規則,然後添加到head里,如果網頁內容變化或者非同步更新等使樣式被移除時,通過事件監聽機制重新添加到head上。 由於只是簡單地改變了body ...
  • 1 function removeClass(obj, aClass) { 2 var re = new RegExp('\\b' + aClass + '\\b'); 3 if (obj.className != '') { 4 5 if (re.test(obj.className)) { 6 ...
  • 1.onselectstart 這個事件主要是用於禁止選擇網頁中的文字。代碼為: document.onselectstart =function(){ return false; } 另外ff/opera不支持此事件,ff可以用css控制:css: body { -moz-user-select: ...
  • 逢10月小長假,幾天不敲鍵盤,渾身難受。也是有時間分享一下自己遇到的css問題。先說一下什麼css hack 簡單介紹一下css hack: 定義: 一般都是利用各瀏覽器的支持CSS的能力和BUG來進行的,可以分為能力選擇和怪癖選擇(BUG)。 能力通常是指瀏覽器對CSS特性的支持程度,而怪癖是指瀏 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...