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

ugl*_*ode 3 google-geocoder angular

我正在使用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()
          };
        });

      });

    });
  }
Run Code Online (Sandbox Code Playgroud)

所以我有几个问题:

  1. 什么时候ngZone用?文档很松散......
  2. 因为这个工作没有runOutsideAngular()那么好,使用它的重点是什么?该示例还包括此函数调用,因此我也实现了它.但它没有它也可以工作......
  3. myObject在视图中还有其他方法可以刷新吗?

谢谢!

Pie*_*Duc 7

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

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

如果你想手动运行更改检测之外的东西,那么如果你想强制某些东西不要触发它,你应该使用runOutsideAngular.这不是您的用例,因此您可以安全地删除它.

此服务最常见的用途是在启动由一个或多个异步任务组成的工作时优化性能,这些异步任务不需要由Angular处理UI更新或错误处理.这些任务可以通过runOutsideAngular启动,如果需要,这些任务可以通过运行重新进入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();
  });
}
Run Code Online (Sandbox Code Playgroud)

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

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

关于NgZone你的'好'读物可以查看api