Angular2-ngZone-google.maps不会触发更改检测 [英] Angular2 - ngZone - google.maps doesn't trigger change detection

查看:107
本文介绍了Angular2-ngZone-google.maps不会触发更改检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Geocoder API,并且在返回结果时,双向数据绑定不起作用.数据只是不会在视图内刷新.如果我手动更改任何其他属性,则数据将被刷新...因此,我搜索了很多(发现)并找到了使用ngZone的解决方案.这是我所做的:

I'm using Geocoder API, and when the results are returned, the two-way data binding doesn't work. The data just doesn't refresh inside the view. If I change any other property manually, the data gets refreshed... So, I googled (a lot) and found a solution that uses ngZone. Here's what I've done:

  getLocation(address: string): void {
    var mygc = new google.maps.Geocoder();
    this._ngZone.runOutsideAngular(() => {

      mygc.geocode({
        'address': address
      }, (results, status) => {

        var data: any = results[0];

        this._ngZone.run(() => {
          this.myObject.myData = {          
            lat: data.geometry.location.lat(),
            lng: data.geometry.location.lng()
          };
        });

      });

    });
  }

所以我有几个问题:

  1. 什么时候使用ngZone?该文档非常宽松...
  2. 由于它也可以在不使用runOutsideAngular()的情况下使用,所以使用它有什么意义?该示例还包括此函数调用,因此我也实现了它.但是没有它也可以工作...
  3. 还有其他方法可以刷新视图中的myObject吗?
  1. When is ngZone used anyway? The documentation is quite loose...
  2. since this works without runOutsideAngular() as well, what's the point of using it? The example includes this function call as well, so I implemented it too. But it works without it as well...
  3. Is there any other way to refresh myObject in the view?

谢谢!

推荐答案

如果我错了,有人会枪杀我,但据我所知,如果在zone.js出现后下载了外部脚本,则需要使用它已加载.这意味着更改检测将不会检测到该脚本内的任何更改.这是稍后加载Google地图时发生的情况.也许....

Someone shoot me if I'm wrong, but as far as I know, you need to use this if you download an external script after zone.js has been loaded. This means that any changes inside that script will not be detected by the change detection. This is what happens when you load the google maps later. Maybe....

无论如何,如果是这种情况,则必须使用ngZone.run方法.

Anyways, if this is the case then you have to use the ngZone.run method.

如果要在更改检测之外手动运行某些内容,因此如果要强制某些内容不触发它,则应使用runOutsideAngular.这不是您的用例,因此您可以放心地删除它.

If you want to run something outside the change detection manually, so if you want to force something not to trigger it, you should use the runOutsideAngular. This is not your use-case, so you can safely remove that.

此服务最常见的用途是在启动一项工作时优化性能,该工作由一个或多个不需要Angular处理UI更新或错误处理的异步任务组成.这些任务可以通过runOutsideAngular启动,如果需要,这些任务可以通过run重新进入Angular区域.

The most common use of this service is to optimize performance when starting a work consisting of one or more asynchronous tasks that don't require UI updates or error handling to be handled by Angular. Such tasks can be kicked off via runOutsideAngular and if needed, these tasks can reenter the Angular zone via run.

但是,另一方面,您提到双向数据绑定对您不起作用(ngModel).我认为真正的问题是您在现有对象上更新属性.这本身不会触发双向更改检测,这是ngZone.run起作用的实际原因.如果是这种情况,则changeRef.detectChanges将不起作用,您最好使用ApplicationRef并执行tick().或者不要使用双向数据绑定并使用data goes down, events go up模式.

But on the other hand, you are mentioning that -two- way data binding doesn't work for you (ngModel). I think the real problem is you updating a property on an existing object. This on itself does not trigger a two way change detection, and is the actual reason why ngZone.run works. If this is the case, then changeRef.detectChanges won't work, and you better use the ApplicationRef and do a tick(). Or don't use two-way data binding and use the data goes down, events go up pattern.

constructor(private appRef: ApplicationRef){}

getLocation(address: string): void {
  let mygc = new google.maps.Geocoder();

  mygc.geocode({
    'address': address
  }, (results, status) => {

      let data: any = results[0];

      this.myObject.myData = {          
         lat: data.geometry.location.lat(),
         lng: data.geometry.location.lng()
      };

      this.appRef.tick();
  });
}

这显然是有效的,因为它与ngZone.run没有什么不同.但是未触发更改检测的主要原因是因为google.maps使用其自己的事件/addEventListener调用集.这些事件不是zone.js所谓的猴子修补,因此不会在Angular区域中运行,因此从逻辑上讲不会触发变更检测周期.

This obviously works, as it is no different from ngZone.run. But the main reason why the change detection is not triggered is because google.maps uses its own sets of events/addEventListener calls. These events are -not- so called monkey patched by zone.js and therefor do not run in the Angular zone, which logically will not trigger a change detection cycle.

因此,您可以使用ngZone.run选项或ApplicationRef.tick解决此问题.我认为ngZone.run最有意义的地方是因为它允许您(重新)输入想要的角度区域.

So you can solve this by either using your ngZone.run option, or the ApplicationRef.tick. Where I suppose the ngZone.run makes the most sense, because it allows you to (re)enter the angular zone, which is exactly what you want.

要获得有关NgZone的良好"阅读,可以查看 api

For a 'good' read about NgZone you can check out the api

这篇关于Angular2-ngZone-google.maps不会触发更改检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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