如何引发Angular2变化检测? [英] How to trigger change detection in Angular2?

查看:534
本文介绍了如何引发Angular2变化检测?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建Facebook的服务调用Facebook的JavaScript API第,我想知道如何最好地实现变化检测,当我的值将被更新。

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

 的currentUser:主题<使用者> =新BehaviorSubject<使用者>(新用户(空));

而当我想回应的JavaScript SDK告诉我,在用户登录或注销Facebook的更新用户,我更新,需要调用打勾()上的 ApplicationRef

  UpdateUser两个(用户:用户){
  的console.log('UserService.updateUser:用户);
  this.currentUser.next(用户);
  this.ap pref.tick(); //用户界面不会没有此更新
}构造函数(脸谱:脸谱){
  this.facebook.facebookEvents.filter(X =>!x =空
         &功放;&安培; x.eventName =='auth.authResponseChange')
      .subscribe((事件)=> {
        this.updateUser(新用户(Event.data中));
      }
}

在我的部分,我从用户服务的currentUser存储在构造函数并绑定到value属性:

 < H2>登录到Facebook的为{{currentUser.value.name}}< / H>
< P>这是你吗? &安培; NBSP; &所述; IMG SRC ={{currentUser.value.profilePicUrl}}>&下; / P>

我是不是做错了什么?难道还有比具有外部库引发的变化之后调用ApplicationRef.tick()更好的办法?

修改

我试着用NgZone并不起作用,使用在饲料通过他们的服务页面返回职位不同的事件:

 构造函数(userService:UserService,私人REF:ApplicationRef,民营区:NgZone)...this.postsSubject.subscribe((后)=> {
  this.zone.runOutsideAngular(()=> {//什么都不做
    this.posts.push(岗位);
    的console.log('postsSubject POST,计数为,this.posts.length);
    ref.tick(); //需要更新绑定
  });
}

控制台显示计数递增,但是HTML结合 {{} posts.length} 如果我添加只更新了 ref.tick ()电话...

我想我看到的地方,你可以从中可能是去为登录用户的方式的顶级应用程序组件使可用的输入到任何组件,而不是其他的呼叫就像在饲料获得职位。 ..


解决方案

  

我是不是做错了什么?难道还有比不必调用一个更好的办法 ApplicationRef.tick()之后的变化从外部触发库?


这要看情况。如果你打电话角以外的Facebook的API(即注册异步事件处理程序外角),那么你就需要手动运行变化检测作为处理任何事件的一部分。您可以


  • 注射 NgZone ,然后调用的run()的对象,将执行传递(回调)函数该角区域内,然后自动调用 ApplicationRef()。打勾(),这将改变运行检测整个应用程序,或

  • ApplicationRef 并调用打勾()自己,或者

  • 注射 ChangeDetectorRef 并调用 detectChanges()自己 - 这将只能运行一个组件变化检测和其子

请注意,如果你注入 NgZone ,你不希望使用 runOutsideAngular()。这将执行传递(回调)函数角区以外,它不会叫 ApplicationRef()。打勾(),所以变化检测将不会执行。

如果你调用内部角Facebook的API,您也许能避免上述所有的,因为那时角(通过其使用Zone.js的)应该猴子修补异步事件调用。然后,当你的活动火, ApplicationRef.tick()将自动被调用。请参见 http://stackoverflow.com/a/34593821/215945 以这种方法进行更多的讨论。

I'm creating a Facebook service that calls the Facebook javascript api and am wondering how to best implement change detection when my values are updated.

I have a UserService which has a currentUser property that is a BehaviorSubject:

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

And when I want to update the user in response to the facebook javascript sdk telling me the user has logged in or logged out, I update that and need to call tick() on an ApplicationRef:

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));
      }
}

In my component I store the 'currentUser' from the user service in the constructor and bind to the value property:

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

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

Edit

I tried using NgZone and that doesn't work, using a different event that returns posts in a feed as the service pages through them:

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
  });
}

The console shows the count incrementing, but the html binding {{posts.length}} is only updated if I add the ref.tick() call...

I think I saw somewhere that you can make available 'inputs' to any component from the top-level app component which might be the way to go for the logged in user, but not other calls like getting posts in a feed...

解决方案

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

It depends. If you're calling the Facebook APIs outside of Angular (i.e., registering asynchronous event handlers outside Angular), then you'll need to manually run change detection as part of handling any events. You can either

  • inject NgZone and then call run() on that object, which will execute the passed (callback) function inside the Angular zone and then automatically call ApplicationRef().tick(), which will run change detection for the entire app, or
  • inject ApplicationRef and call tick() yourself, or
  • inject ChangeDetectorRef and call detectChanges() yourself -- this will only run change detection on the one component and its children

Note, if you inject NgZone, you don't want to use runOutsideAngular(). That will execute the passed (callback) function outside the Angular zone, and it will not call ApplicationRef().tick(), so change detection will not execute.

If you call the Facebook APIs inside Angular, you might be able to avoid all of the above, because then Angular (via its use of Zone.js) should monkey-patch the asynchronous event calls. Then, when your events fire, ApplicationRef.tick() will automatically be called. See http://stackoverflow.com/a/34593821/215945 for more discussion on this approach.

这篇关于如何引发Angular2变化检测?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆