私は、チャット表示用の単純な自動スクロール ディレクティブに取り組んできました。
@Directive({
selector: "[autoScroll]"
})
export class AutoScroll {
@Input() inScrollHeight;
@Input() inClientHeight;
@HostBinding("scrollTop") outScrollTop;
ngOnChanges(changes: {[propName: string]: SimpleChange}) {
if (changes["inScrollHeight"] || changes["inClientHeight"]) {
this.scroll();
}
};
scroll() {
this.outScrollTop = this.inScrollHeight - this.inClientHeight;
};
}
このディレクティブは、設定したenableProdMode()
場合ChangeDetectionStrategy
とデフォルトに設定されている場合に機能しますが、「開発モード」では例外が発生します。ChangeDetectionStrategy
をに設定できますonPush
。その場合、例外は発生しませんが、スクロールは遅れます。
Dom が更新されてから Scroll 関数を呼び出すことができるように、このコードをより適切に構造化する方法はありますか? 試してみましsetTimeout()
たが、遅延が悪化ChangeDetectorRef
し、オブザーバブルを使用してトリガーしてサブスクライブしようとしましたmarkForCheck()
。を使用するngAfterViewChecked()
と、ブラウザがクラッシュします。
@Component({
selector: "chat-display",
template: `
<div class="chat-box" #this [inScrollHeight]="this.scrollHeight" [inClientHeight]="this.clientHeight" autoScroll>
<p *ngFor="#msg of messages | async | messageFilter:username:inSelectedTarget:inTargetFilter:inDirectionFilter" [ngClass]="msg.type">{{msg.message}}</p>
</div>
`,
styles: [`.whisper {
color: rosybrown;
}`],
directives: [NgClass, AutoScroll],
pipes: [AsyncPipe, MessageFilterPipe],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChatDisplay implements OnInit {
username: string;
@Input() inSelectedTarget: string;
@Input() inTargetFilter: boolean;
@Input() inDirectionFilter: boolean;
messages: Observable<ChatType[]>;
constructor(private socketService_: SocketService, private authService_: AuthService) {
this.username = this.authService_.username;
};
ngOnInit() {
}
}
これは、dev モードのときにトリガーされる例外です。
例外: 式 'this.scrollHeight in ChatDisplay@1:40' は、チェック後に変更されました。以前の値: '417'。現在の値: [ChatDisplay@1:40 の this.scrollHeight] angular2.dev.js の '420' (23083,9)