Angular 17中如何获取基于Signal的Input的前后值?
在Angular Signal Input中获取属性的前后值
方案一:基于RxJS的改进实现(解决pairwise首次无输出问题)
你提到的pairwise仅在第二次及以后发射时输出,只需通过startWith补充初始值就能覆盖首次场景:
import { Component, input } from '@angular/core'; import { toObservable } from '@angular/core/rxjs-interop'; import { pairwise, startWith } from 'rxjs'; @Component({ selector: 'app-example', standalone: true, template: `<p>当前值:{{ inputProp() }}</p>` }) export class ExampleComponent { // 定义Signal Input,可设置默认值 inputProp = input<string>(); constructor() { toObservable(this.inputProp) .pipe( // 补充初始前值(用undefined或对应默认值) startWith(undefined), pairwise() ) .subscribe(([previousValue, currentValue]) => { // 这里可执行类似ngOnChanges的逻辑 console.log(`前值: ${previousValue}, 当前值: ${currentValue}`); }); } }
startWith会给Observable添加一个初始发射值,这样第一次inputProp变化时,pairwise就能输出[初始值, 当前值],后续每次变化也能正常获取前后值。
方案二:纯Signal实现(无需RxJS)
如果不想引入RxJS,可以通过维护一个私有Signal来保存前值,结合effect监听变化:
import { Component, input, effect, signal } from '@angular/core'; @Component({ selector: 'app-example', standalone: true, template: `<p>当前值:{{ inputProp() }}</p>` }) export class ExampleComponent { inputProp = input<string>('默认值'); // 初始化前值为Input的初始值 private previousInputValue = signal<string>(this.inputProp()); constructor() { effect(() => { const currentValue = this.inputProp(); const previousValue = this.previousInputValue(); // 这里可访问前后值,执行业务逻辑 console.log(`前值: ${previousValue}, 当前值: ${currentValue}`); // 更新前值,供下次effect触发时使用 this.previousInputValue.set(currentValue); }); } }
如果想和ngOnChanges行为完全一致(仅在Input实际变化时触发逻辑,排除初始化首次执行),可以加一个标记区分首次运行:
import { Component, input, effect, signal } from '@angular/core'; @Component({ selector: 'app-example', standalone: true, template: `<p>当前值:{{ inputProp() }}</p>` }) export class ExampleComponent { inputProp = input<string>('默认值'); private previousInputValue = signal<string>(this.inputProp()); private isFirstRun = signal(true); constructor() { effect(() => { const currentValue = this.inputProp(); const previousValue = this.previousInputValue(); if (!this.isFirstRun()) { // 仅在非首次执行时处理变化逻辑 console.log(`前值: ${previousValue}, 当前值: ${currentValue}`); } this.previousInputValue.set(currentValue); this.isFirstRun.set(false); }); } }
方案选择
- 纯Signal方案更轻量,适合不需要RxJS的场景;
- RxJS方案适合已有RxJS依赖的项目,或需要结合其他操作符处理复杂数据流的场景。
内容的提问来源于stack exchange,提问作者Lakhveer
相关产品推荐
相关产品推荐

