Angular2 - ngZone - google.maps不会触发更改检测

时间:2017-02-02 10:55:06

标签: angular google-geocoder

我使用Geocoder API,当返回结果时,双向数据绑定不起作用。数据在视图内部不会刷新。如果我手动更改任何其他属性,数据会刷新...所以,我google(很多)并找到使用ngZone的解决方案。这就是我所做的:

  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吗?
  4. 谢谢!

2 个答案:

答案 0 :(得分:6)

如果我错了,有人会向我开枪,但就我所知,如果在加载zone.js后下载外部脚本,则需要使用此功能。这意味着更改检测不会检测到该脚本内的任何更改。这是您稍后加载谷歌地图时发生的情况。也许....

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

如果您想手动运行更改检测之外的某些内容,那么如果您想强制某些内容不能触发它,则应使用runOutsideAngular。这不是您的用例,因此您可以安全地删除它。

  

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

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

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区域中运行,这在逻辑上不会触发更改检测周期。

因此,您可以使用ngZone.run选项或ApplicationRef.tick来解决此问题。在哪里我认为ngZone.run最有意义,因为它允许你(重新)进入角度区域,这正是你想要的。

关于NgZone的“好”阅读,您可以查看api

答案 1 :(得分:1)

我简单地使用:

{{1}}