NgrxStore 和 Angular - 大量使用异步管道或在构造函数中只订阅一次
Posted
技术标签:
【中文标题】NgrxStore 和 Angular - 大量使用异步管道或在构造函数中只订阅一次【英文标题】:NgrxStore and Angular - Use the async pipe massively or subscribe just once in the constructor 【发布时间】:2017-06-02 03:23:05 【问题描述】:我开始关注 ngrx Store,我看到了使用 Angular 异步管道的便利。同时我不确定是否大量使用 Angular 异步管道是一个不错的选择。
我举一个简单的例子。假设在同一个模板中,我需要显示从 Store 中检索到的对象(例如 Person)的不同属性。
一段模板代码可以是
<div>(person$ | async).name</div>
<div>(person$ | async).address</div>
<div>(person$ | async).age</div>
而组件类构造函数应该有
export class MyComponent
person$: Observable<Person>;
constructor(
private store: Store<ApplicationState>
)
this.person$ = this.store.select(stateToCurrentPersonSelector);
.....
.....
据我了解,这段代码意味着 3 个订阅(通过异步管道在模板中进行)到同一个 Observable (person$
)。
另一种方法是在 MyComponent 中定义 1 个属性 (person
),并且只有 1 个订阅(在构造函数中)填充该属性,例如
export class MyComponent
person: Person;
constructor(
private store: Store<ApplicationState>
)
this.store.select(stateToCurrentPersonSelector)
.subscribe(person => this.person = person);
.....
.....
而模板使用标准属性绑定(即没有异步管道),例如
<div>person.name</div>
<div>person.address</div>
<div>person.age</div>
现在的问题
这两种方法在性能方面有什么不同吗?大量使用异步管道(即大量使用订阅)会影响代码的效率吗?
【问题讨论】:
您可能需要考虑在容器中对“哑”组件的输入使用异步管道。查看example-app
和Presentational and Container Components 中的组件和容器。
【参考方案1】:
您也不应该将您的应用程序编写为智能和演示组件。
优点:
智能控制器上的所有业务逻辑。 只需订阅一次 可重用性 展示控制器只有一个职责,只展示数据,不知道数据从哪里来。 (松散耦合)回答最后一个问题:
大量使用异步管道会影响效率,因为它会订阅每个异步管道。如果您正在调用 http 服务,您会注意到这一点,因为它会为每个异步管道调用 http 请求。
智能组件
@Component(
selector: 'app-my',
template: `
<app-person [person]="person$ | async"></app-person>
`,
styleUrls: ['./my.component.css']
)
export class MyComponent implements OnInit
person$: Observable<Person>;
constructor(private store: Store<ApplicationState>)
ngOnInit()
this.person$ = this.store.select(stateToCurrentPersonSelector);
演示组件
@Component(
selector: 'app-person',
template: `
<div>person.name</div>
<div>person.address</div>
<div>person.age</div>
`,
styleUrls: ['./my.component.css']
)
export class PersonComponent implements OnInit
@Input() person: Person;
constructor()
ngOnInit()
更多信息请查看:
https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.u27zmzf25 http://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/【讨论】:
我很欣赏拆分智能组件和演示组件的价值。出于您提到的所有原因,这很有意义。如果我们只看故事的“代码效率”方面,我是否正确地假设使用一个“异步管道”和许多“属性绑定”比使用“许多异步管道”更有效?提前谢谢 与我想要询问的信息完全相同。非常感谢! 很好的答案,但是在使用带有路由器的子组件时它会有什么用处?【参考方案2】:另一种可能性是使用这样的构造:
<div *ngIf="person$ | async as per">
<div> per.name </div>
<div> per.address </div>
<div> per.age </div>
<div>
虽然对于可重用的代码位,使用表示组件方法可能更好。
请注意这适用于 Angular 5,不确定其他版本。
【讨论】:
我喜欢这个,因为它将智能和演示组件融合到一个代码块中。出于完全相同的原因,我不喜欢这个。 :) 如何在控制器中访问per
?我猜现在的方式?【参考方案3】:
您可以在任何可观察声明的末尾添加“.share()”。一个 observable 上的所有异步管道都将共享同一个订阅:
this.name$ = Observable.create(observer =>
console.log("Subscriber!", observer);
return observer.next("john")
).delay(2000).share();
this.httpget$ = http.get("https://api.github.com/").share();
Plunkr 演示: https://embed.plnkr.co/HNuq1jUh3vyfR2IuIe4X/
【讨论】:
以上是关于NgrxStore 和 Angular - 大量使用异步管道或在构造函数中只订阅一次的主要内容,如果未能解决你的问题,请参考以下文章
StoreModule.forRoot() 和 StoreModule.forFeature() 有啥区别
NativeScript + ngrx 存储 + 远程开发工具