从组件类中的observable获取唯一/最新值(商店选择器的结果)

时间:2018-02-20 04:03:42

标签: angular ngrx

我的应用程序正在使用Angular和ngrx存储。 我在商店中使用选择器来获取组件构造函数中的app状态的username属性:

测试component.ts

export class TestComponent {
    username$: Observable<string>;
    constructor(private store: Store<fromRoot.AppState>) {
        this.username$ = this.store.select(fromRegistration.getUsername);
    }

    testMethod() {
         //I need the value of the username observable here as a string
    }

}

这很好用。 我需要在组件模板中打印用户名,我正在使用异步管道进行操作:

测试component.html

<div>
{{username | async}}
</div>

这也正常。

现在,我需要从TestComponent中的一个方法调用一个服务,该方法将用户名作为参数发送。我怎样才能做到这一点?我是否需要停止使用异步管道并订阅选择器然后将username属性(然后将其声明为字符串)分配给observable的值?

要注意:用户名observable只有1个值,一旦我得到1个值,我就可以停止观看了。

我理解通过使用异步管道,组件可以自动取消订阅用户名observable,何时发生这种情况以及组件如何知道我不再需要观看它?

如果我不能使用异步管道,我何时以及何时取消订阅?

2 个答案:

答案 0 :(得分:2)

首先想到

在您的情况下解决此问题的最佳方法是创建一个组件输入变量并从父异步传递它。

export class TestComponent {
    @Input()
    username: string;

    testMethod() {
         //I need the value of the username observable here as a string
    }

}

以下是父组件的外观:

@Component({
     template: '<test-component [username]="username$ | async">'
})
export class ParentComponent {
    username$: Observable<string>;
    constructor(private store: Store<fromRoot.AppState>) {
        this.username$ = this.store.select(fromRegistration.getUsername);
    }
}

另一种解决方案

您还可以在子组件中设置局部变量:

export class TestComponent {
    usernameString: string
    username$: Observable<string>;
    constructor(private store: Store<fromRoot.AppState>) {
        this.username$ = this.store.select(fromRegistration.getUsername);
        this.username$.subscribe(name -> this.usernameString = name);
    }

    testMethod() {
        if (this.usernameString != undefined) {
            //do something
        }
    }
}

答案 1 :(得分:2)

我通常使用Maciej Treder's First thought,因为我尝试尽可能使用哑组件,但在某些情况下,当我需要来自选择器的新值来执行我的组件中的额外内容时,我将转向异步管道它仍然是我的模板(所以我不需要任何订阅),我只使用rxjs 点击运算符,pipeable operator do名称Maciej Treder's second solution。所以我替换了这个:

ngOnInit() {
  this.selected$ = this.store.pipe(select(fromItems.getSelectedBrand));
}

由此:

import { Store, select } from '@ngrx/store';
import { tap } from 'rxjs/operators';

...

ngOnInit() {
  this.selected$ = this.store.pipe(
    select(fromItems.getSelectedBrand),
    tap((brand: Brand) => {
      /**
       * do logic here
       */
    })
  );
}

现在,如果由于某些原因你确实需要订阅它而没有像How to unsubscribe from ngrx/store?那样将其同步管理到任何模板,我建议使用ngOnDestroy取消订阅它。你会在这里找到更多相关信息: