使用OnPush策略时,不会重新渲染子组件的视图

时间:2017-08-06 16:30:59

标签: angular typescript ngrx

@Component({
    selector: "parent",
    template: `<child [userId]="(userId$ | async)"></child>`,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ParentCmp implements OnInit {
    userId$: BehaviorSubject<string> = new BehaviorSubject<string>(null);

    constructor(private activatedRoute: ActivatedRoute) { }
    ngOnInit() {
        this.activatedRoute.queryParams.subscribe(query => {
            //notify child with BehaviorSubject
            this.userId$.next(query["userid"])
        }
    }
}

@Component({
    selector: "child",
    template: `<div *ngIf="(userState$ | async) && userId">
                    {{(userState$ | async).user.id)}}
               </div>`,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildCmp implements OnChanges {
    @Input() userId: string;
    private userState$: Observable<User>;

    constructor(private store: Store<store.AppState>) { }
    ngOnChanges(changes: SimpleChanges) { 
        //when it gets userId it starts to track fit user in ngrx store
        this.userState$ = this.store
                .select(state => state.user-list)                 
                .map(userList => userList[this.userId])
                .filter(user => !!user);
    }
}

Child cmp从Parent 1获取userId,并且所需用户包含在ngrx store(userList)中,但不会重新呈现子视图。当Child的ChangeDetectionStrategy是默认值时,它完美地工作。这可能有什么不对? Angular v2.4

1 个答案:

答案 0 :(得分:0)

如果您在ngOnChanges()中更改模型,则需要明确调用更改检测

export class ChildCmp implements OnChanges {
    @Input() userId: string;
    private userState$: Observable<User>;

    constructor(
      private store: Store<store.AppState>,
      private cdRef:ChangeDetectorRef
    ) { }
    ngOnChanges(changes: SimpleChanges) { 
        //when it gets userId it starts to track fit user in ngrx store
        this.userState$ = this.store
                .select(state => state.user-list)                 
                .map(userList => userList[this.userId])
                .filter(user => !!user);
        this.cdRef.detectChanges();
    }
}

或者可能更好地使userStates$成为一个Observable并保持相同的实例,而不是每次调用ngOnChanges时创建一个新实例:

userId$: Subject<User> = new Subject<User>();

ngOnChanges(changes: SimpleChanges) { 
    //when it gets userId it starts to track fit user in ngrx store
    this.store
            .select(state => state.user-list)                 
            .map(userList => userList[this.userId])
            .filter(user => !!user)
            .subscribe((user) => this.userId.next(user));
}