【问题标题】:Can an @Input binding be an observable in Angular?@Input 绑定可以在 Angular 中是可观察的吗?
【发布时间】:2017-12-12 09:20:40
【问题描述】:

我正在创建一个在输入字段下显示验证错误的组件。如果显示错误消息,并且用户提交了我想闪烁消息以引起他们注意的表单。

我想知道是否可以使用 observable 作为输入绑定?

这样我可以订阅输入并在观察到任何数据时闪烁。

这是我的想法的一个例子:

@Component({..})
export class MessageComponent implement OnChanges {
   @Input()
   public flash: Observable<any>;

    public ngOnChanges(changes: SimpleChanges): void {
        if ('flash' in changes) {
            (<Observable<any>> changes['flash'].currentValue).subscribe(() => {
                // trigger the flash animation here
            });
        }
    }
}

我不知道这是否会泄漏内存,以及我应该如何/何时取消订阅(或者是否有必要)。

Angular 允许这种做法吗?

【问题讨论】:

    标签: angular rxjs observable


    【解决方案1】:

    是的,您可以使用 observable 作为输入。

    您是否需要取消订阅取决于相关的 observable。当 observable 完成或出错时,所有订阅者都会自动取消订阅。因此,一般来说,如果您知道 observable 完成,则不需要显式取消订阅。

    但是,看看您的 sn-p,这似乎是次要问题,因为您编写的代码表明您希望输入发生变化。

    在这种情况下,您应该在发生更改时取消订阅。否则,您将有两个订阅者 - 第一个订阅者仍在收听原始的 flash observable。

    import { Subscription } from 'rxjs/Subscription';
    
    @Component({..})
    export class MessageComponent implement OnChanges, OnDestroy {
    
        @Input()
        public flash: Observable<any>;
        private flashSubscription: Subscription;
    
        public ngOnChanges(changes: SimpleChanges): void {
            if ('flash' in changes) {
                if (this.flashSubscription) {
                    this.flashSubscription.unsubscribe();
                }
                this.flashSubscription = (<Observable<any>> changes['flash'].currentValue).subscribe(() => {
                    // trigger the flash animation here
                });
            }
        }
    
        public ngOnDestroy(): void {
            if (this.flashSubscription) {
                this.flashSubscription.unsubscribe();
            }
        }
    

    我还会在ngOnDestroy 中调用unsubscribe - 这样对于未完成或错误的flash observables 将取消订阅。

    请注意,多次调用订阅的unsubscribe 方法是安全的。

    【讨论】:

    • 另外,您可能想要测试 flash 更改为 nullundefined
    【解决方案2】:

    如果消息的来源是可观察的,那么使用异步管道可能会更好。

    <app-message [message]="message$ | async"></app-message>
    

    这将为您处理关于清理的订阅。

    那么既然你已经在使用ngOnChanges——它只在发生变化时触发——所以你只需在message发生变化时触发动画。

    public ngOnChanges(changes: SimpleChanges): void {
        if ('message' in changes) {
    
            // trigger the flash animation here
        }
    }
    

    对于这个例子,没有必要让你的消息控件订阅事物并期望一个可观察的作为输入。

    或者,您可以使用动画和:enter 事件在首次显示消息时显示动画。每次都闪烁很烦人。

    如果您真的想使用某种外部触发器来触发闪光(我意识到您可能简化了您的示例),那么您可以使用指令进行调查,以便稍后重用它。 (那么您可能需要使用 AnimationBuilder)。这是一条更复杂的路线。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-17
      • 2014-06-23
      • 2012-11-02
      • 2017-11-25
      • 2014-10-29
      • 1970-01-01
      • 2021-09-25
      • 1970-01-01
      相关资源
      最近更新 更多