📜  在 Angular 11 中建立兄弟组件之间的通信

📅  最后修改于: 2021-10-29 06:18:57             🧑  作者: Mango

在本文中,我们将看到如何在客户端机器上的兄弟组件之间传递数据。

在 Angular 中,我们将我们的网页分成多个组件,这些组件之间的关系形成了一个树状结构。一个组件可能有一个父组件和多个子组件。也就是说,它也可以有兄弟姐妹。在某些情况下,我们需要在这些独立组件之间传递数据。传递数据很容易,它使我们的代码在处理大型项目时更清晰、更具可读性。

先决条件:必须预先安装 NPM。

要了解其工作原理,请参见下图:

  • 在用户事件的情况下,我们可以从一个组件发出数据。
  • 此数据将发送到父组件。
  • 父组件可以进一步将此数据以输入的形式传输到另一个子组件。
  • 这是一种单向传输,但我们可以使用另一种方式来建立双向通信通道。

在 Angular 中,我们可以使用其内置功能来实现这一点:

  • @Output 装饰器有助于通过 EventEmitter 对象发出数据。我们将通过示例看到它的工作原理。
  • 父组件会将数据作为 $event 变量捕获。它可以在一种方法中使用它或通过其他方式传输它。
  • 最后 @Input() 装饰器使用一个变量,任何通过父级的输入都将存储在这个变量中。

让我们通过一个简单的例子来了解这一切。在这篇文章中,我们将看到一个简单的网页,它在一个组件中将关键字作为用户输入,并在另一个组件中显示匹配的行。

让我们先设置环境:

  • 安装角度cli。以管理员身份运行或在权限错误的情况下使用 sudo。
npm i -g @angular/cli
  • 安装 angular CLI 后,使用以下命令启动一个新项目:
ng new 
  • 现在使用以下方法测试它:
ng serve -o
  • 如果http://localhost:4200可以访问angular登陆页面,则设置成功。在进一步移动之前清除 app.component.html 的内容。
  • 之后生成两个新组件:
ng generate component search
ng generate component table
  • 您将在 app 文件夹中看到两个目录“search”和“table”。他们都将有 4 个新文件。

让我们制作我们的搜索组件并从中发出一个事件。首先在search.component.html 中编写以下代码:

HTML


         
    
    


Javascript
import { Component, EventEmitter, OnInit, Output } 
        from '@angular/core';
  
@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
  
  constructor() { }
  ngOnInit(): void {
  }
  @Output() emitter:EventEmitter
       = new EventEmitter();
  
  emit(keyword){
      this.emitter.emit(keyword);
  }
}


Javascript
import { Component, DoCheck, Input, OnInit } from '@angular/core';
  
@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit, DoCheck {
  data = [
    {name:"Liam", age:"20", post: "Marketing Coordinator"},
    {name:"Noah", age:"25" , post:"Medical Assistant"},
    {name:"Oliver", age:"22", post:"Web Designer"},
    {name:"William", age:"20", post:"Dog Trainer"},
    {name:"Bill", age: "22", post:"President of Sales"},
    {name:"James", age: "19", post:"Project Manager"},
  ];
  items = [];
  constructor() { }
  @Input() keyword:string;
  
  ngOnInit(): void {
    this.refresh();
  }
  
  ngDoCheck(){
    this.refresh();
  }
  
  refresh(){
    this.items = [];
    this.data.forEach(
      item => {
        if(item.name.search(this.keyword) != -1
         || item.age.search(this.keyword) != -1 
         || item.post.search(this.keyword) != -1) {
          this.items.push(item)
        }
      }
    ) 
  }
}


HTML

No results found

                                            
                                    
NameAgePost
{{item.name}}{{item.age}}{{item.post}}


Javascript
import { Component } from '@angular/core';
  
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'GeeksForGeeks';
  keyword = "";
  send(keyword){
    this.keyword = keyword;
  }
}


HTML
  

  
  


在上面的代码中,有一个简单的输入字段,它在 keyup 事件发生时使用了一个 emit()函数。我们将使用它向父组件发出关键字。让我们在search.component.ts 中定义这个方法和事件:

Javascript

import { Component, EventEmitter, OnInit, Output } 
        from '@angular/core';
  
@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
  
  constructor() { }
  ngOnInit(): void {
  }
  @Output() emitter:EventEmitter
       = new EventEmitter();
  
  emit(keyword){
      this.emitter.emit(keyword);
  }
}

“字符串”类型的发射器对象将在其发射()方法中发射指定的参数。在 keyup 事件上,emit() 方法执行发射器对象的 emit() 方法。

现在让我们填充table.component.ts 中的代码:

Javascript

import { Component, DoCheck, Input, OnInit } from '@angular/core';
  
@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit, DoCheck {
  data = [
    {name:"Liam", age:"20", post: "Marketing Coordinator"},
    {name:"Noah", age:"25" , post:"Medical Assistant"},
    {name:"Oliver", age:"22", post:"Web Designer"},
    {name:"William", age:"20", post:"Dog Trainer"},
    {name:"Bill", age: "22", post:"President of Sales"},
    {name:"James", age: "19", post:"Project Manager"},
  ];
  items = [];
  constructor() { }
  @Input() keyword:string;
  
  ngOnInit(): void {
    this.refresh();
  }
  
  ngDoCheck(){
    this.refresh();
  }
  
  refresh(){
    this.items = [];
    this.data.forEach(
      item => {
        if(item.name.search(this.keyword) != -1
         || item.age.search(this.keyword) != -1 
         || item.post.search(this.keyword) != -1) {
          this.items.push(item)
        }
      }
    ) 
  }
}

对于这个例子,我们已经声明了一个数据对象,它是我们表的一些静态数据。

  • 使用@Input() 装饰器将“关键字”变量定义为此组件的输入。
  • 我们已经声明了一个 refresh() 方法,该方法使用“关键字”变量在任何一个字段中匹配的内容来填充项目列表。
  • 我们已经在 ngDoCheck 和 ngOnInit 方法中调用了这个方法(注意我们必须为它们实现接口)。 ngDoCheck 方法在应用程序中称为更改后检测。因此,每当 parent 中的关键字更改时,此方法将替换列表。
  • 我们将使用以下代码在 table.component.html 上显示此列表:

HTML

No results found

                                            
                                    
NameAgePost
{{item.name}}{{item.age}}{{item.post}}

上面的代码显示了“items”数组中的表格。现在让我们为父组件app.component.ts编写代码:

Javascript

import { Component } from '@angular/core';
  
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'GeeksForGeeks';
  keyword = "";
  send(keyword){
    this.keyword = keyword;
  }
}

在上面的代码中:

  • 我们已经声明了一个关键字变量。
  • send() 方法将关键字作为参数并将其设置为类变量。
  • 我们将使用类变量“keyword”作为表格组件的输入。
  • 搜索组件发出的事件将由 send() 方法处理。
  • 请参阅下面的app.component.html代码:

HTML

  

  
  

在这段代码中:

  • “$event”变量表示从搜索组件发出的数据。
  • 表组件的关键字变量作为 [keyword] 传递。

现在保存所有文件并使用以下命令测试代码:

ng serve -o

在 http://localhost:4200 上我们可以看到结果。

输出: