几乎完全如果您搜索通过服务进行跨组件通信的示例,这些示例将在服务内部使用 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();
}
}
只要组件使用默认的 ChangeDetectionStrategy,您的示例就可以工作。 让我们仔细看看一个非常简化且不太精确的解释,说明用户单击增量按钮时会发生什么:
不要太深入细节,当使用 OnPush 时,Angular 会跳过检查该组件及其所有子组件,除非更改了某些输入,或者将该组件标记为通过例如进行检查。打电话给
ChangeDetectorRef.markForCheck()
。这是一种常见的模式,从服务中获取可观察量并通过
async
管道在模板中绑定到它,每次 Observable 发出值时管道都会调用
markForCheck
。所以虽然变更检测周期仍然需要被触发,但它是一个 Observable 值更新使组件被检查,那些没有变化的组件根本不会被检查。对于派生状态和副作用,假设我们有两个服务 A 和 B,当 A 中的值更新时需要在 B 中执行某些操作。如果没有 Observables,则需要将 B 注入到 A 中,如果我们有几十个这样的服务会怎样?连接?它很快就会变得混乱。对于组件来说也是如此,很常见的情况是,在渲染值之前应该对其进行转换,与另一个值组合,然后才进行渲染。虽然这可以在 getter 内部完成,但在每个 CD 周期上运行它们会浪费资源。
最后一件事是,Angular 的一些 API 以 Observable 的形式出现,例如反应式表单、路由器事件、HttpClient,因此当它也是基于 Observable 时,将它们放入您自己的东西中会更简单。