我有组件树,每个组件都有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));
});
}
}