场景很简单,调用远程方法,返回的Observable对象的subscribe方法中,(或者Promise的then),更新了数据模型,但是视图没有渲染。
task.component.html
<div class="vertical-form-container">
<form #taskForm>
<mat-form-field>
<input matInput #title type="text" name="title" placeholder="Title" required [(ngModel)]="taskData.title">
</mat-form-field>
<mat-form-field class="example-full-width">
<input matInput #deadlineDate name='deadlineDate' [matDatepicker]="picker" placeholder="Deadline Date" required [(ngModel)]="taskData.deadlineDate">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker touchUi="true" #picker></mat-datepicker>
</mat-form-field>
<mat-form-field class="example-full-width">
<textarea matInput matTextareaAutosize minRows='2' maxRows='10' #description name='description' placeholder="Task Description" [(ngModel)]="taskData.description"></textarea>
</mat-form-field>
<button mat-raised-button color="primary" type="button" (click)='submitTask()'>ADD</button>
</form>
</div>
task.component.ts
......
// taskService是Service,通过taskId远程(非angular的http)获取数据
this.taskService.getTask(taskId).subscribe(
resp=>{
console.log('get task: ----------------');
console.log(resp);
this.taskData = resp; // 场景一,View不更新
// this._ngZone.run(()=>this.taskData = resp); //场景二,使用NgZone,View会更新
/* 场景二,View会更新, changeDetectorRef是注入的ChangeDetectorRef
this.taskData = resp;
this.changeDetectorRef.markForCheck();
this.changeDetectorRef.detectChanges(); */
}
);
......
方式一就无法更新视图,而且如果在方式一中使用router.navigate(...)
也会不正常;方式二可以更新视图,但是如果每次都要把回调用ngZone.run()
封装起来也太不优雅了;方式三和方式二差不多,而且在angular-material下不正常。
不知道有什么好办法可以解决一下这个问题?还是我哪里写的有问题吗?
如果你不使用内置的
http
服务,同时zonejs
又没有对你使用的请求服务做patched
的话,只能手动触发了。对于代码本身,我认为和优雅不优雅没有关系,因为既然没有使用内置的http服务,那自己需要额外的代码来解决问题。不过通过
NgZone.runOutsideAngular
把在Angular作用域外执行的方法包裹起来可能比直接调用在请求方法返回的回调中调用NgZone.run
优雅一些?