我有组件树,每个组件都有changeDetection: ChangeDetectionStrategy.OnPush
,在这种情况下,祖先组件不会检测它们正在进行的本地更改,例如,observables或setTimeout()
。我这样做是通过添加this.ref.markForCheck()
调用来更新组件的。但我想这可能不是解决问题的好方法。
那么这样做的真正方法是什么?我是对的,如果我使用第三方组件并且它没有this.ref.markForCheck()
调用它可能不起作用吗?
这是我最低级别组件的代码:
import {
Component, HostBinding, ViewEncapsulation, AfterContentInit,
Input, ViewChild, ElementRef, ChangeDetectionStrategy, ChangeDetectorRef,
} from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import * as $ from 'jquery';
import { DestroyUnsubscribe } from 'services';
@Component({
selector: 'jf-more',
encapsulation: ViewEncapsulation.None,
// changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['more.component.scss'],
template: `
<div class="more__open-button" *ngIf="!opened" (click)="onToggleClick()">
<ng-content select="jf-more-open"></ng-content>
</div>
<div class="more__text" [ngClass]="{'more__text_opened': opened}" #text>
<ng-content></ng-content>
</div>
<div class="more__close-button" *ngIf="opened" (click)="onToggleClick()">
<ng-content select="jf-more-close"></ng-content>
</div>
`,
})
@DestroyUnsubscribe()
export class MoreComponent implements AfterContentInit {
@Input() oneLineHeight = 16;
@ViewChild('text') text: ElementRef;
@HostBinding('class.more') mainClass = true;
@HostBinding('class.more_initiated') initiated: boolean = false;
@HostBinding('class.more_one-line') oneLine: boolean;
opened: boolean;
private subscriptions: Subscription[] = [];
constructor(private ref: ChangeDetectorRef) {}
ngAfterContentInit() {
this.makeLineCheck();
this.subscriptions.push(
Observable
.fromEvent(window, 'resize')
.debounceTime(500)
.subscribe(() => this.makeLineCheck())
);
}
onToggleClick() {
this.opened = !this.opened;
// this.ref.detectChanges();
// this.ref.markForCheck();
}
private makeLineCheck() {
this.initiated = false;
this.opened = true;
this.oneLine = false;
// this.ref.detectChanges();
this.ref.markForCheck();
console.log('makeLineCheck', Object.assign({}, this));
setTimeout(() => {
this.oneLine = ($(this.text.nativeElement).innerHeight() <= this.oneLineHeight);
this.initiated = true;
this.opened = false;
// this.ref.detectChanges();
this.ref.markForCheck();
console.log('setTimeout makeLineCheck', Object.assign({}, this));
});
}
}
答案 0 :(得分:2)
ApplicationRef.tick()
或setTimeout(...)
调用根节点的更改检测,然后向下传播。如果两者之间的组件设置为OnPush
并且没有输入更改,则这不会导致这些组件中的更改检测。
我会使用带有observables的共享服务来通知祖先他们为自己调用markForCheck()
的变化。