对于以下代码,似乎UI并未使用该值进行更新,但是,我可以看到该值已正确设置为字段。
我尝试了2种不同的方法,但我还没有尝试过变更检测方法,因为我相信下面代码中的一种,应该可以工作。
在我的服务中,我监听路由结束事件,其原因是,根据我的路由中参数的存在,需要更改服务中的某些内容,例如:'/ page /:id'
在一种情况下,URL可能是/ page,在另一种情况下是/ page / 12,因此基于这一事实,我需要从两个不同的服务返回值,如果ID不存在,请使用SERVICE1否则,请使用SERVICE2。
我基本上有一个订阅,该订阅从另一个订阅返回值。为此,我依靠“订阅”从内部订阅中发出值,该方法有效(请参见下面的示例)。我的苦恼是,UI无法呈现值。
主要服务
注意:为简洁起见,省略了整个类,只是为了显示所讨论的方法:
get getCourse(): Observable<CoursesDTO> {
let subject = new Subject<CoursesDTO>();
this.router.events.pipe(filter(e => e instanceof NavigationEnd))
.subscribe(x => {
let course: CoursesDTO = {
courseName: '',
courseId: ''
};
const route = this.router.routerState.snapshot.root;
let courseId: string = '';
if (route.children.length >= 1) {
const obj = route.children[route.children.length - 1];
const value = (obj.params as any).value;
// we have a courseID, interact with the course workflow
if (!_.isEmpty(value)) {
this.courseWorkflowProxy.interact(value.courseId, 'CourseMaterial', null)
.subscribe((b: InteractionResponseDTO) => {
const x: CourseDTO = <any>b.workflowResult;
course = {
courseName: x.courseName,
courseId: x.courseId
};
subject.next(course);
subject.complete();
return course; // I don't feel this is necessary
});
}
}
// we don't have the courseID, so assume there is a JWT token
// for example, that authenticated the user + courseID
// and we can get this in the code behind
this.coursesProxy
.getCourseInfo()
.subscribe(b => {
course = {
courseName: b.courseName,
courseId: b.courseid
};
subject.next(course);
subject.complete();
return course; // I don't feel this is necessary
});
});
return subject;
}
请注意,此代码已被修改为代表该代码,而不是“实际”情况,如果感觉不对,则用于代码演示。
此方法在名为WatchBlock.ts的组件中的实现,显示了我尝试通过ngZone进行的可能的修复之一:
this.whatBlockService.getCourse.subscribe((r: CourseDTO) => {
this._ngZone.run(() => {
this.title = r.courseName;
this.id = r.courseId;
console.dir({ title: this.title, id: this.id }); // this prints the values to the console
});
});
以下代码在“返回结果”的意义上阻止了“工作”,但是如上所述,它不会出现在呈现的HTML中。
HTML文件:
<div fxLayout="row" fxLayoutAlign="start center">
<div class="ml-16">
<label class="identi">{{id}}</label>
</div>
</div>
<div class="px-8 px-mat-16">
<span class="mat-title">{{title}}</span>
</div>
我也尝试过BehaviorSubject方法,但这对我也不起作用。
我没有尝试过变更检测器路由,因为如果我了解分区的工作原理,我认为ngZone应该自己进行变更检测。
我不知道这一点,并希望得到那里的专家的帮助。
答案 0 :(得分:0)
实际上,不可以,在NgZone中运行代码不能确保更改检测器将检测到更改。如果组件或任何父组件设置为ChangeDetectionStrategy.OnPush
,它将仅检查输入。如果您不致电zone.runOutsideAngular
,则通常不需要运行ngZone.run
。
但是您可以尝试在组件private _changeDetectorRef: ChangeDetectorRef
回调中注入this._changeDetectorRef.markForCheck()
并调用subscribe
。使用markForCheck
策略时,OnPush
将组件标记为手动更改。 Docs