簡體   English   中英

Angular:如何將數據從子組件發送到父組件?

[英]Angular: how to send data from child component to parent component?

我正在學習 Angular。 我已經閱讀了文檔和五篇博文,一切都一清二楚。 我認為有兩個模板。 子模板有一個按鈕。 當用戶單擊按鈕時,我希望在父模板中顯示一個元素(說明卡)。 當用戶再次單擊按鈕時,我希望該元素不顯示。 即,子按鈕打開和關閉父元素。

<button (click)="toggleInstructions()">Instructions</button>

在我的頭(子)組件中,我制作了一個輸出事件發射器sendData 、一個布爾變量showInstructions和一個在truefalse之間切換showInstructions的函數。 在記錄showInstructions (效果很好!)之后,它會調用sendData來發出數據。 我創建了一個新變量myData因為我對this的使用感到困惑。

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent {
  @Output() sendData = new EventEmitter<boolean>();

  showInstructions: boolean = false;

  toggleInstructions(myData: boolean) {
    console.log("Clicked!");
    switch (true) {
      case (this.showInstructions === true):
      this.showInstructions = false;
      break;

      case (this.showInstructions === false):
      this.showInstructions = true;
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log(this.showInstructions);
    myData = this.showInstructions;
    console.log(myData);
    this.sendData.emit(myData);
  }
}

在父組件中,我導入了子組件( HeaderComponent )並創建了一個函數toggledInstructions來接收數據。 當我單擊按鈕時,沒有記錄任何內容。

import { Component } from '@angular/core';
import { HeaderComponent } from './header/header.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  toggledInstructions(myData: boolean) {
    console.log("Data coming in!");
    console.log(myData);
  }
}

我很困惑這應該如何工作。 除了數據變量名稱( myData )之外,我在連接發送和接收函數的文檔中看不到任何內容。

謝謝你的幫助!

我發現這個 ZeroesAndOnes 博客文章很好地解釋了這一點。 要解決我的答案,請從博客文章開始並啟動其代碼。

child.component.html更改為:

<div style="border: solid 1px gray; padding: 15px; margin-top: 15px;">
    <h2>Child Component</h2>
    <button (click)="clickButton()">Show Element in Parent</button>
</div>

子模板沒有什么特別之處。 只是一個觸發控制器功能的按鈕。

child.component.ts更改為:

import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
})
export class ChildComponent {
  showElement: boolean = false;
  @Output() buttonClicked: EventEmitter<boolean> = new EventEmitter<boolean>();

  clickButton() {
    console.log("(Child) Value before toggle: " + this.showElement);
    console.log("(Child) Button clicked!");
    switch (true) {
      case (this.showElement === true):
      this.showElement = false;
      break;

      case (this.showElement === false):
      this.showElement = true;
      break;

      default:
      console.log("Error in switch-case.");
    }
    console.log("(Child) Value after toggle: " + this.showElement);
    this.buttonClicked.emit(this.showElement);
  }

}

變量列表以showElement開頭,它是一個boolean並被初始化為false ,即父元素是隱藏的。

接下來是另一個變量,它是 Angular 魔法的第一位。 變量是buttonClicked並且它有裝飾器@Output() 這個裝飾器意味着該變量將在控制器之外可用。 該變量的類型為EventEmitter<boolean>並且它被分配了一個新的事件發射器。 如果您喜歡較短的行,則可以省略該類型:

@Output() buttonClicked = new EventEmitter<boolean>();

接下來是在truefalse之間切換showElement的函數。 在這個函數的底部是 Angular 魔法的第二位。 調用輸出事件並發送showElement變量以由事件發射器發射。

現在將父模板app.component.html更改為:

<div style="border: solid 1px gray; padding: 15px;">
  <app-child (buttonClicked)="parentEventHandlerFunction($event)">
  </app-child>
  
  <h1>Parent Component</h1>
  <span><b>Value emitted from child component is:</b></span>
  {{ valueEmittedFromChildComponent }}
  
  <div *ngIf="valueEmittedFromChildComponent"><span style="color: red;"><b>My awesome element!</b></span>
  </div>
  
</div>

Angular 的大魔法在父模板中,特別是在這一行中:

  <app-child (buttonClicked)="parentEventHandlerFunction($event)">
  </app-child>

指令app-child將子模板嵌入到父模板中。 buttonClicked是子控制器中的事件發射器。 parentEventHandlerFunction是父控制器中的一個函數。 $event是從孩子發送給父母的對象。 這一行將子控制器和父控制器的部分組合在一起,用等號將它們連接起來。 這就是 Angular 的巨大魔力。

現在設置父控制器app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  valueEmittedFromChildComponent: boolean;

  parentEventHandlerFunction(valueEmitted){
    this.valueEmittedFromChildComponent = valueEmitted;
    console.log("(Parent) Value emitted: " + valueEmitted);
  }
}

我們有一個名為valueEmittedFromChildComponent變量,它是一個boolean 然后我們有一個函數parentEventHandlerFunction和一個參數valueEmitted $event對象來自父模板中的魔法線,並分配給局部變量valueEmittedFromChildComponent

回到父模板,我們顯示局部變量valueEmittedFromChildComponent並在*ngIf使用它來顯示和隱藏元素。

ZeroesAndOne 總結了他們的博客文章,“總而言之,Angular 可以非常輕松地創建使用 @Output() 裝飾器向其父組件發送數據的子組件。” 哈! 這不是我所說的“極其容易”。 相比之下,在 AngularJS 中,兩個模板將共享一個控制器。 一個模板中的按鈕綁定到控制器中的一個函數,該函數切換一個變量,該變量綁定到第二個模板中的元素以顯示和隱藏元素。 數據從第一個模板到控制器中的單個變量再到第二個模板。 這“非常容易”。

在 Angular 中,子模板中的按鈕會觸發子控制器中的一個函數,與 AngularJS 相同。 但是隨后您需要使用事件發射器制作一個@Output()裝飾器,並從切換函數中調用事件發射器。 然后數據被發送到父模板中的魔術線,它結合了來自子控制器和父控制器的東西。 然后數據進入父控制器,然后返回父模板以顯示或隱藏目標元素。

讓我們重復一遍。 當用戶單擊子模板中的按鈕時,數據進入子控制器,在那里函數切換值,然后將數據從函數發送到事件發射器。 事件發射器將數據發送到父模板,父模板將數據發送到父控制器,父控制器將數據發送回父模板以顯示或隱藏元素。 這不是我所說的容易。

你會如何在 React 中做到這一點? React 更像 AngularJS 還是 Angular?

看起來您需要$event變量來獲取發出的值:

<button (click)="toggleInstructions($event)">Instructions</button>

toggledInstructions(event: boolean) {
    console.log("Data coming in!", myData);
}

事件綁定(fooevent)允許綁定到 DOM 事件和EventEmitter事件

更新:

工作代碼示例:

ChildComponent.ts:

@Output() public onFooClicked = new EventEmitter<boolean>();

showMenu() {
  this.onFooClicked .emit(true);
}

app.component.ts:

<foo (onFooClicked)="onClicked($event)">
</foo>

onClicked(event: boolean) {
    console.log(`Somebody clicked`, event);
}

此外,還有一篇很棒的文章如何傳遞數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM