【问题标题】:Why doesn't my view update?为什么我的视图没有更新?
【发布时间】:2018-03-20 00:08:18
【问题描述】:

在下面的代码中,如您所见,我订阅了一个 observable,在回调中我将 status 设置为 result 的值。这用于视图上的 *ngIf。事实是,即使返回 true,视图也不会更新。

  export class AppComponent {

  private status;

  constructor (private proxyService: ProxyService) {

  }

  ngOnInit(){
    //setInterval(()=>console.log(this.isInjected),1000);
    this.proxyService.someObservable.subscribe((result)=>{
      this.status = result;
      console.log(result);
    });
  }

}

现在,您可能会注意到注释行。在调试时我添加了它,奇怪的是它使视图更新。任何想法为什么?

仅供参考,这是我的看法:

  <div *ngIf="status">
    <app-userlane-inject></app-userlane-inject>
  </div>
  <div *ngIf="!status">
    <span>Status is false.</span>
  </div>
{{status}}

子组件永远不会被渲染,字符串插值即使在控制台记录为真时也保持假(除非有间隔,那么它可以工作)。

从广义上讲,该服务的作用如下:

var mySubject= new BehaviorSubject(false);


@Injectable()
export class ProxyService {
  public someObservable= mySubject.asObservable();


//Kinda deep callback tree, then finally
  mySubject.next(true)

}

只是一些额外的信息来将答案放入上下文中:我上面提到的深度回调链完全脱离了角度(这是一个扩展,调用链包括向内容脚本发送消息,然后到页面,以及一路回来)。 这就是为什么需要再次调用角区。 我不知道这是原因,这就是为什么我没有在我最初的问题中包含这个原因。

【问题讨论】:

  • 你不需要var me = this;。只需使用this.status = result;
  • 什么是ProxyService?你能分享一些代码吗?
  • console.log(result) 的输出是什么;
  • 输出为真,就是这样
  • 这很方便@jason.kaisersmith,谢谢。这就是我添加间隔控制台日志时尝试做的事情,但这解决了问题哈哈。可能是 ngZone 的事情,我对此一无所知。

标签: angular


【解决方案1】:

我认为如果你在类之外初始化mySubject,它将在Angulars区域之外运行,这将阻止Angular识别事件,因此不会运行更改检测。

@Injectable()
export class ProxyService {
  private mySubject= new BehaviorSubject(false);
  public someObservable= this.mySubject.asObservable();


//Kinda deep callback tree, then finally
  this.mySubject.next(true)
}

更新

你可以使用

  constructor(private zone:NgZone) {}
  this.zone.run(()=> this.mySubject.next(true));

但是如果这解决了你的问题,那么调用链中可能有问题,在 Angulars 区域内没有发生某些事件或回调。

【讨论】:

  • 刚试过这个,有道理。但没有修复。也许我的回调树将执行从 ngZone 带走(它肯定可能)?我会试试 ngZone.run。
  • this.ngZone.run(()=&gt;this.isInjected = result); 解决了。所以这不是可观察的,而是.next 将其从区域中带走之前的调用树。你的回答让我明白了,如果你更新修复,我会接受。谢谢。
  • 我更新了我的答案。你找到根本原因在哪里?
  • 嗯,是的...该调用通过 tabs.sendMessage 转到内容脚本,然后通过 dom 事件转到页面,然后返回相同的路径...所以它离开该区域并不奇怪。该解决方案有效,并且是扩展开发必须了解的。
【解决方案2】:

显示 observable 的最佳方式是创建一个哑组件来显示它们。

例子:

如果this.status 是可观察的

创建一个哑组件来显示它。

//dumb component to display status

   @Component({
      selector: 'dumb-display-comp',
      template: '{{ status }}'  
    })
    export class DumbDisplayComp {
        @Input() status: any;
    }

现在在父组件中使用哑组件,并使用异步管道将可观察对象作为输入发送。

使用哑组件的父模板

<dumb-display-comp [status]="status | async" ></dumb-display-comp>

您的应用应该充满愚蠢的组件,以整理您的主要组件。 只是我的两分钱。

【讨论】:

    猜你喜欢
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    相关资源
    最近更新 更多