【angular教程240109】06 Angular父子组件以及非父子组件之间通讯

【angular教程240109】06 Angular父子组件以及组件之间通讯

目录:

  • [【angular教程240109】06 Angular父子组件以及组件之间通讯](#【angular教程240109】06 Angular父子组件以及组件之间通讯)
    • [一、子组件获取父组件的数据、执行子组件的方法 父组件给子组件传值-@input](#一、子组件获取父组件的数据、执行子组件的方法 父组件给子组件传值-@input)
    • [二、子组件通过@Output 结合事件驱动实现组件通讯](#二、子组件通过@Output 结合事件驱动实现组件通讯)
      • [1 子组件](#1 子组件)
    • [三、 父组件发送/接受到子组件的数据、父组件执行子组件方法 (综合)](#三、 父组件发送/接受到子组件的数据、父组件执行子组件方法 (综合))
    • [四、 非父子组件通讯](#四、 非父子组件通讯)
      • [1. 服务与依赖注入(DI)](#1. 服务与依赖注入(DI))
      • [2. RxJS Subjects 和 Observables](#2. RxJS Subjects 和 Observables)
      • [3. NgRx](#3. NgRx)
      • [4. 事件总线(Event Bus)](#4. 事件总线(Event Bus))
      • [5. Local Storage 或 Session Storage](#5. Local Storage 或 Session Storage)
      • [6. Query Params 或 Router State](#6. Query Params 或 Router State)

一、子组件获取父组件的数据、执行子组件的方法 父组件给子组件传值-@input

1子组件

html 复制代码
<p>header works!-------------</p>
<header>{{title}}--{{msg}}</header>
<br>
<button (click)="getParentMsg()">子组件header里面获取父组件hone传入的数据msg</button>
<br>
<button (click)="getParentRun()">子组件header里面执行父组件home的run方法</button>
<p>header works!-------------</p>
ts 复制代码
 import { Component, OnInit, Input } from '@angular/core';
@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
  //接受父组件传来的数据
  @Input() title: any;
  @Input() msg: any;
  //接受父组件传来的方法
  @Input() run: any;
  //传入整个父组件
  @Input() home: any;
  constructor() {}
  ngOnInit() {}
  //执行父组件的run 方法
  // this.run();
  getParentMsg() {
    //获取父组件的数据
    alert(this.msg);
  }
  getParentRun() {
    //执行父组件的run 方法
    // this.run();
    alert(this.home.msg);
    this.home.run();
  }
}

二、子组件通过@Output 结合事件驱动实现组件通讯

1 子组件

html

html 复制代码
<p>footer works!</p>
<button (click)="sendParent()">我是子组件footer来给父组件广播数据  </button> 
ts 复制代码
import { Component,OnInit,Output,EventEmitter } from '@angular/core';
// Output 和 EventEmitter 分别用于定义输出属性和创建事件发射器。
// 代码是Angular组件编程中常见的一部分,
// 用于定义一个可以发射事件给其父组件的输出属性。这是实现Angular组件间通信的一种方式。
@Component({
  selector: 'app-footer',
  templateUrl: './footer.component.html',
  styleUrls: ['./footer.component.scss']
})
export class FooterComponent implements OnInit{
  @Output() private myouter=new EventEmitter;
  /* 
  这是一个装饰器(Decorator),用于Angular的组件(Component)中。
@Output() 表明这是一个输出属性,允许该组件向其父组件发送数据。
private outer = new EventEmitter; 
创建了一个新的事件发射器(EventEmitter)实例,并将其赋值给私有属性outer。
这个事件发射器用于发射事件。
*/
  ngOnInit(): void {
    throw new Error('Method not implemented.');
  }
  sendParent(){
    alert(123244);
  this.myouter.emit('号外号外!!!我是一个来自子组件footer的数据')
  }
}

三、 父组件发送/接受到子组件的数据、父组件执行子组件方法 (综合)

父组件

html 复制代码
<hr><p>-------------home works!</p>
<app-header [title]="title"  [msg]="msg"  [home]="this" ></app-header>
<!--Angular组件标签。[title]、[msg]和[home]是属性绑定,它们将父组件的属性值传递给子组件。-->
<!-- <app-footer  (myouter)="run()"></app-footer> -->
<app-footer  (myouter)="run($event)"></app-footer>
<!--这里的run($event)会在myouter事件触发时执行,$event是事件对象。-->
<p>-------------home works!</p>
<hr>
ts 复制代码
import { Component, OnInit } from '@angular/core';

// 定义一个组件,指定选择器、HTML模板和样式文件的URL
@Component({
  selector: 'app-home', // 定义组件的选择器,用于在HTML中引用
  templateUrl: './home.component.html', // 指定组件的HTML模板文件
  styleUrls: ['./home.component.scss'], // 指定组件的样式文件
})
export class HomeComponent implements OnInit {
  ngOnInit(): void {} // ngOnInit是生命周期钩子,组件初始化时调用

  public title: string = '我是首页home的title'; // 定义一个公共属性title
  public msg: string = '我是首页home的msg'; // 定义一个公共属性msg

  // run方法,被子组件触发的事件处理函数
  run(e: any) {
    alert('我是父组件的run方法'); // 显示警告框
    console.log(e); // 在控制台输出事件对象
  }

  handleChild() {} // 定义一个空方法,可能用于未来的子组件交互
}

或,上一片文章:父组件通过@ViewChild主动获取子组件的数据和方法

四、 非父子组件通讯

在Angular中,非父子组件(即兄弟组件或完全不相关的组件)之间的通信可以通过多种方式实现。这些通信方式适用于当组件没有直接的层级关系时。以下是几种常见的通信方法:

1. 服务与依赖注入(DI)

服务是Angular中一个非常强大的特性,可以用来在组件之间共享数据和行为。你可以创建一个可注入的服务来充当中介,通过它来进行组件间的通信。

typescript 复制代码
@Injectable({
  providedIn: 'root' // 提供在根模块中,这样整个应用都可以访问这个服务
})
export class DataService {
  private data = new BehaviorSubject<any>(null);

  setData(value: any) {
    this.data.next(value);
  }

  getData(): Observable<any> {
    return this.data.asObservable();
  }
}

任何组件都可以注入这个服务,并使用它来发送或接收数据。

在Angular中,当使用 @Injectable 装饰器并设置 providedIn: 'root' 属性时,服务默认是以单例(Singleton)模式提供的。这意味着整个应用中只会创建该服务的一个实例,无论它被注入到多少个组件或其他服务中。

这是一个单例服务的例子:

typescript 复制代码
@Injectable({
  providedIn: 'root'
})
export class SingletonService {
  // 这个服务的实例将在整个应用中是唯一的
}

这种单例行为确保了服务的状态和逻辑在应用 的不同部分之间保持一致。不过,Angular也允许将服务的作用域限定到特定模块或组件。如果服务在一个Angular模块或组件中的 providers 数组 里提供,那么该服务的实例将限定在该模块或组件及其子组件中。这种情况下,服务不再是单例的。

例如:

typescript 复制代码
@NgModule({
  providers: [NonSingletonService] // 这将为每个导入该模块的消费者创建服务的新实例
})
export class SomeModule { }

在上面的例子中,NonSingletonService 对于导入 SomeModule 的每个消费者来说都是一个新的实例。

总结来说,是否为单例取决于服务是如何提供的:

使用 providedIn: 'root' 或提供到 AppModule:服务是应用级别的单例。

提供到特定模块的 providers:每个导入该模块的消费者都会获得服务的新实例。

提供到组件的 providers:每个组件实例都会获得服务的新实例,只用于该组件及其子组件。

2. RxJS Subjects 和 Observables

RxJS是一个库,它提供了强大的数据流控制能力。Angular服务通常使用RxJS中的 Subject 或 BehaviorSubject 来创建可观察的数据流。

typescript 复制代码
 
// 在服务中
private mySubject = new Subject<any>();

sendMessage(message: string) {
  this.mySubject.next(message);
}

getMessage(): Observable<any> {
  return this.mySubject.asObservable();
}

// 在发送消息的组件中
this.dataService.sendMessage('Hello from Component A!');

// 在接收消息的组件中
this.dataService.getMessage().subscribe(message => {
  console.log(message); // 输出 'Hello from Component A!'
});

3. NgRx

NgRx是一个基于RxJS的框架,用于在Angular应用中管理状态和允许组件间的通信。它提供了一个全局的状态管理,通过Actions和Reducers来处理状态的更新。

4. 事件总线(Event Bus)

虽然这不是Angular推荐的做法,但在某些情况下,创建一个事件总线(Event Bus)可以作为组件间通信的手段。通常,这涉及到创建一个服务,该服务包含一个 Subject,允许发送和接收消息。

5. Local Storage 或 Session Storage

对于需要持久化数据,或者在用户导航到不同页面时保持数据的场景,你可以使用Web Storage API(如Local Storage或Session Storage)来存储数据。

6. Query Params 或 Router State

如果组件间的通信与路由导航有关,你可以使用路由的Query Params或Router State来传递数据。

选择哪种方法取决于的具体需求,例如:

如果需要一个集中式的状态管理,可能会选择NgRx。

如果希望通过订阅模式来共享数据,可能会选择使用服务和RxJS。

对于更简单的需求,可能使用Local Storage或Session Storage更为直接。

Angular的服务和RxJS通常是最常见和推荐的方法,因为它们提供了一种清晰和响应式的方式来处理应用状态和事件。

相关推荐
2401_882727571 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder1 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂1 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand2 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL2 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
六卿2 小时前
react防止页面崩溃
前端·react.js·前端框架
z千鑫2 小时前
【前端】详解前端三大主流框架:React、Vue与Angular的比较与选择
前端·vue.js·react.js
m0_748256143 小时前
前端 MYTED单篇TED词汇学习功能优化
前端·学习
小马哥编程4 小时前
Function.prototype和Object.prototype 的区别
javascript
小白学前端6664 小时前
React Router 深入指南:从入门到进阶
前端·react.js·react