角度反应性和通过服务进行通信

问题描述 投票:0回答:1

几乎完全如果您搜索通过服务进行跨组件通信的示例,这些示例将在服务内部使用 RxJS(现在也可以是信号)。不过,这似乎没有必要。例如,即使在以下服务的情况下,两个组件都能够在不使用 RxJS 或信号的情况下看到计数器的更改。

在这种情况下不使用 RxJS 或 Signals 有什么缺点吗?我认识到使用 RxJS 或 Signals 是在 Angular 中执行操作的规定方式,这是这样做的一个很好的理由,但我想知道除此之外是否还有其他实际原因。这会导致任何类型的问题或错误吗?

下面是示例服务,这是示例 Stackblitz。

服务:

import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class MyService { private counter: number = 0; increment() { this.counter += 1; } getValue() { return this.counter; } }
组件1:

import { Component } from '@angular/core'; import { MyService } from './MyService'; @Component({ selector: 'component1', standalone: true, template: ` <h1>Component 1</h1> Current Value: {{ valueFromService }} <button (click)="increment()">Click to increment</button> `, }) export class Component1 { constructor(private myService: MyService) {} get valueFromService() { return this.myService.getValue(); } increment() { this.myService.increment(); } }
组件 2:

import { Component } from '@angular/core'; import { MyService } from './MyService'; @Component({ selector: 'component2', standalone: true, template: ` <h1>Component 2</h1> Current Value: {{ valueFromService }} `, }) export class Component2 { constructor(private myService: MyService) {} get valueFromService() { return this.myService.getValue(); } }
    
angular angular-services
1个回答
0
投票
使用 Observables 与 OnPush ChangeDetectionStrategy 配合得很好,通常会对运行时性能产生积极影响。它还使得处理派生状态、处理多个同时更新以及运行副作用作为对状态更新的反应变得更加简单。

只要组件使用默认的 ChangeDetectionStrategy,您的示例就可以工作。 让我们仔细看看一个非常简化且不太精确的解释,说明用户单击增量按钮时会发生什么:

    触发“点击”事件
  1. 关联事件处理程序的任务被添加到事件循环中
  2. 当浏览器决定是时候从事件循环中运行内容时,它会运行处理程序,以便更改服务中的状态
  3. Zone.js(Angular 在内部使用的一个库,用于监视其他不透明的事件循环状态)通知 Angular 事件循环队列为空,并且 Angular 运行更改检测
  4. 在变更检测周期期间,Angular 重新渲染组件,此时组件从服务中提取新值
因此服务值更新和呈现值更新是分开的。如果值由于 Zone.js 无法拦截的某些内容(例如 awync/await)而更新,则视图将不会反映更改。值得注意的是,事件可能会经常发生,检查每个事件的每个组件可能会成为一项相当繁重的任务。这就是为什么使用 OnPush ChangeDetectionStrategy 被认为是更好的做法。

不要太深入细节,当使用 OnPush 时,Angular 会跳过检查该组件及其所有子组件,除非更改了某些输入,或者将该组件标记为通过例如进行检查。打电话给

ChangeDetectorRef.markForCheck()

。这是一种常见的模式,从服务中获取可观察量并通过 
async
 管道在模板中绑定到它,每次 Observable 发出值时管道都会调用 
markForCheck
。所以虽然变更检测周期仍然需要被触发,但它是一个 Observable 值更新使组件被检查,那些没有变化的组件根本不会被检查。

这是一个演示

对于派生状态和副作用,假设我们有两个服务 A 和 B,当 A 中的值更新时需要在 B 中执行某些操作。如果没有 Observables,则需要将 B 注入到 A 中,如果我们有几十个这样的服务会怎样?连接?它很快就会变得混乱。对于组件来说也是如此,很常见的情况是,在渲染值之前应该对其进行转换,与另一个值组合,然后才进行渲染。虽然这可以在 getter 内部完成,但在每个 CD 周期上运行它们会浪费资源。

最后一件事是,Angular 的一些 API 以 Observable 的形式出现,例如反应式表单、路由器事件、HttpClient,因此当它也是基于 Observable 时,将它们放入您自己的东西中会更简单。

© www.soinside.com 2019 - 2024. All rights reserved.