0

对于以下代码,UI 似乎没有使用该值更新,但是,我可以看到该值被正确设置为该字段。

我尝试了 2 种不同的方法,bar 没有尝试过更改检测方法,因为我相信下面代码中的方法应该可以工作。

在我的服务中,我监听路由结束事件,原因是,服务中的某些内容需要根据我的路由中是否存在参数进行更改,例如:'/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 应该自己进行更改检测。

我无法弄清楚这一点,并希望从那里的大师那里得到任何帮助。

4

1 回答 1

0

实际上,不,在 NgZone 中运行代码并不能确保更改检测器能够检测到更改。如果组件或任何父组件设置为ChangeDetectionStrategy.OnPush,它只会检查输入。如果您不调用zone.runOutsideAngular,则(通常)不需要运行ngZone.run

但是您可以尝试在组件回调中注入private _changeDetectorRef: ChangeDetectorRef和调用。使用策略时手动将组件标记为已更改。文档this._changeDetectorRef.markForCheck()subscribemarkForCheckOnPush

于 2019-03-08T07:39:59.937 回答