typescript - 如何在 Angular2 中触发变化检测?

标签 typescript angular angular2-changedetection

<分区>

我正在创建一个调用 Facebook javascript api 的 Facebook 服务,我想知道如何在我的值更新时最好地实现变更检测。

我有一个 UserService,它有一个 currentUser 属性,它是一个 BehaviorSubject:

currentUser: Subject<User> = new BehaviorSubject<User>(new User(null));

当我想更新用户以响应 facebook javascript sdk 告诉我用户已登录或注销时,我更新它并需要在 上调用 tick() >应用引用:

updateUser(user: User) {
  console.log('UserService.updateUser:', user);
  this.currentUser.next(user);
  this.appRef.tick(); // UI does not update without this
}

constructor(facebook: Facebook) {
  this.facebook.facebookEvents.filter(x => x != null 
         && x.eventName == 'auth.authResponseChange')
      .subscribe((event) => {
        this.updateUser(new User(event.data));
      }
}

在我的组件中,我将来自用户服务的“currentUser”存储在构造函数中并绑定(bind)到值属性:

<h2>Logged into Facebook as {{currentUser.value.name}}</h2>
<p>Is this you? &nbsp; <img src="{{currentUser.value.profilePicUrl}}"></p>

我做错了什么吗?有没有比在从外部库触发更改后必须调用 ApplicationRef.tick() 更好的方法?

编辑

我尝试使用 NgZone 但它不起作用,使用不同的事件返回 feed 中的帖子作为服务页面通过它们:

constructor(userService: UserService, private ref: ApplicationRef, private zone: NgZone)

...

this.postsSubject.subscribe((post) => {
  this.zone.runOutsideAngular(() => { // doesn't do anything
    this.posts.push(post);
    console.log('postsSubject POST, count is ', this.posts.length);
    ref.tick(); // required to update bindings
  });
}

控制台显示计数递增,但 html 绑定(bind) {{posts.length}} 仅在我添加 ref.tick() 调用时更新。 .

我想我在某处看到您可以从顶级应用程序组件向任何组件提供可用的“输入”,这可能是登录用户的方式,但不是其他调用,例如在提要中获取帖子。 ..

最佳答案

Am I doing something wrong? Is there a better way than having to call ApplicationRef.tick() after a change triggered from an external library?

这取决于。如果您在 Angular 外部调用 Facebook API(即在 Angular 外部注册异步事件处理程序),那么您需要手动运行更改检测作为处理任何事件的一部分。你也可以

  • 注入(inject) NgZone 然后在该对象上调用 run(),这将在 Angular 区域内执行传递的(回调)函数,然后自动调用 ApplicationRef ().tick(),这将为整个应用程序运行更改检测,或者
  • 注入(inject) ApplicationRef 并自己调用 tick(),或者
  • 注入(inject) ChangeDetectorRef 并自己调用 detectChanges() —— 这只会在一个组件及其子组件上运行变化检测

请注意,如果您注入(inject) NgZone,您不想使用 runOutsideAngular()。这将在 Angular 区域外执行传递的(回调)函数,并且它不会调用 ApplicationRef().tick(),因此不会执行更改检测。

如果您在 Angular 中调用 Facebook API,您可能能够避免上述所有情况,因为 Angular(通过使用 Zone.js)应该猴子修补异步事件调用。然后,当您的事件触发时,ApplicationRef.tick() 将自动被调用。参见 https://stackoverflow.com/a/34593821/215945有关此方法的更多讨论。

关于typescript - 如何在 Angular2 中触发变化检测?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35520018/

相关文章:

typescript - 如何从 TypeScript 中的枚举值构建类型?

angular - ExpressionChangedAfterItHasBeenCheckedError 解释

Angular 性能 - OnPush 增加循环次数

jquery - 使用高亮filterData在全局变量上不显示过滤器数据意味着不在Typescript中的功能

AmCharts 的 TypeScript 声明

typescript - Angular 2 : ngOnInit is called AFTER trying to render template when start from url with id

angular - 从字符串动态创建 Angular 组件

dart - pub serve 找不到 lib 下的文件

javascript - Angular 6 : Real time data

javascript - Angular 2,带 setter 的 @Input 的行为是否与不带 setter 的 @Input 不同?