我正在开发一个具有Facebook之类的墙的应用程序,其中包含帖子组件(具有点赞的计数器)和嵌套评论组件,这些组件按需通过帖子内的按钮加载。我正在使用NgRx商店,并且按照以下步骤操作时会出现意外行为:
number
动作LikePost
动作,并使用新的post对象(已更新点赞的次数)作为有效负载。然后更新点赞计数器。LikePostSuccess
属性后,子post.likesCount
会重新初始化(而内部的数据没有更改),这会使显示闪烁。它的实现方式以及到目前为止我尝试过的工作:
CommentsComponent
和两个不同的reducer来管理帖子和评论。@ngrx/entity
中,我设置了PostsComponent
changeDetection: ChangeDetectionStrategy.OnPush
方法)时会发生这种行为,但是如果我只是以可变的方式直接更改属性adapter.UpdateOne()
,则可以解决问题,但这是一个坏习惯。post.likesCount
)获得的Observable在组件中显示此likesCount
。然后,我认为对数据的引用将不会移动,并且不会进行子级初始化,但是它不起作用。 posts.component.html
likesCount$(post) | async as likesCount
comments.component.html
<ng-container *ngFor="let post of posts">
<div>{{ post.title }}</div>
<button (click)="likePost(post)">
<mat-icon>thumb_up</mat-icon>
<span>{{ post.likesCount }}</span>
</button>
<button (click)="toggleComments(post)">
<mat-icon>chat_bubble</mat-icon>
</button>
<div>
<ng-container *ngIf="comments$(post) | async as comments">
<app-comments [comments]="comments" [postId]="post.id"></app-comments>
</ng-container>
</div>
</ng-container>
posts.reducer.ts
<ul>
<li *ngFor="let comment of comments">{{ comment.content }}</li>
</ul>
posts.component.ts
const reducer = createReducer(
initialState,
// ...
on(postsActions.likePostSuccess, (state, props) => {
const update: Update<Post> = {
id: props.post.id,
changes: {
likesCount: props.post.likesCount
}
};
return postsAdapter.updateOne(update, state);
})
// ...
);
最后,问题是:如何在不触发子级初始化的情况下更新父级组件属性?这里的问题是孤立的,但是我无法想象如果我有很多嵌套的组件会发生什么。
问题是否来自ChangeDetection?从商店状态更新的方式(可变/不可变)?使用// ...
comments$(post: Post): Observable<UserComment[]> {
return this.store.pipe(select(selectCommentsByPostId(post.id)));
}
// ...
库是不错的选择吗?
谢谢您的帮助
答案 0 :(得分:0)
正如我所见,您更新了帖子,然后对其进行迭代,然后在该迭代中,您仅创建了一个新的子组件,这就是为什么要重新初始化子组件的原因。
答案 1 :(得分:0)
解决方案是在* ngFor中使用trackBy
,以强制Angular保持对象的相同引用,从而无需重新初始化它。