【问题标题】:Angular2 + Google Maps API Idle event listener issueAngular2 + Google Maps API 空闲事件监听器问题
【发布时间】:2016-12-24 23:31:40
【问题描述】:

我在使用 Angular2 + GMaps API 时遇到了这个问题。 我想在地图加载并设置一些标记时显示微调器预加载器。 当使用 addListenerOnce IDLE 监听器时,在第一次调用监听器控制我的范围时,我的组件中的变量“this”变成了映射本身,所以当我想在监听器中执行一些函数或回调时,例如,如果我写类似:

public isLoaded: boolean = false;
...
google.maps.event.addListener(map, 'idle', () => {
this.isLoaded= true;
});

变量 THIS 进入监听器(那应该引用组件范围)变成谷歌地图本身,因此 this.isLoaded 返回未定义(isLoaded 是我的组件中的一个属性而不是地图属性)。就像监听器控制了我的组件范围,

奇怪的是这种情况发生了一次,当组件第一次加载时,它会修复并且一切正常。

有什么解决办法吗?对不起我的英语不好。 提前致谢!

【问题讨论】:

    标签: google-maps angular scope spinner preloader


    【解决方案1】:

    在你的函数执行集的 sn-p 上下文中,由 Gmap 显式设置,如回调.apply(this, args)

    因此,对于您的情况,您只需要明确设置上下文,为此,函数具有 .bind() 方法 (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)

    public isLoaded: boolean = false;
    ...
    
    const myCallback = () => {
    this.isLoaded= true;
    };
    
    google.maps.event.addListener(map, 'idle',myCallback.bind(this));
    

    【讨论】:

    • 好的,尝试使用旧的解决方案 - 在回调外部声明变量引用这个。常量自我 = 这个; google.maps.event.addListener(map, 'idle', () => { self.isLoaded= true; });
    • 也没有工作。你能看看我在这个之后发的帖子吗?谢谢
    • 嗨 Nicolas,您的 sn-p 没有隐藏,因为您只更改变量值而 ng2 不知道此更改。您需要通过使用 detectChages() 方法显式运行检测周期。
    • 将此添加到您的构造函数中:constructor(private _detector: ChangeDetectorRef) {} 并将其添加到 gmap 回调中:google.maps.event.addListenerOnce(this.map, 'idle', function () { this .loaded = true; this.detector.detectChanges(); console.log("THIS INSIDE listener callback:", this) }.bind(this));
    • 非常感谢,成功了!!!不得不添加一些额外的东西,因为当微调器隐藏时我的地图画布都是灰色的,所以我添加: google.maps.event.addListenerOnce(this.map, 'idle', function () { this.loaded = true; this. _detector.detectChanges(); google.maps.event.trigger(this.map,'resize'); this.map.setCenter({ lat: this.latitude, lng: this.longitude }); console.log("这个INSIDE listener callback:", this) }.bind(this));
    【解决方案2】:

    感谢 Valikhan Akhmedov,我的 GMap 预加载器正在运行!最终解决方案:

    ...
    
    constructor(private _detector: ChangeDetectorRef){}
    
        ngOnInit() { this.initMap(); }
    
        initMap() {
            this.map = new google.maps.Map(document.getElementById('map-canvas'), {
                center: { lat: this.latitude, lng: this.longitude },
                zoom: this.zoom
            });
    
            google.maps.event.addListenerOnce(this.map, 'idle', function () {
                this.loaded = true;
                this._detector.detectChanges();
                google.maps.event.trigger(this.map,'resize');
                this.map.setCenter({ lat: this.latitude, lng: this.longitude });         
            }.bind(this));
        }
    

    【讨论】:

      【解决方案3】:

      还是不行。好吧,我想我可以通过将 .bind(this) 添加到我的回调中来解决范围问题,如下所示:

       console.log("THIS OUTSIDE listener callback:", this)
              google.maps.event.addListenerOnce(this.map, 'idle', function () {
                  this.loaded = true;
                  console.log("THIS INSIDE listener callback:", this)
              }.bind(this));
      

      控制台输出为:

      "THIS OUTSIDE listener callback: MapaComponent {loaded: false, latitude: 31.7413, longitude: -60.5115, bounds: _.ae, zoom: 12…}"
      "THIS INSIDE listener callback: MapaComponent {loaded: true, latitude: -31.7413, longitude: -60.5115, bounds: _.ae, zoom: 12…}"
      

      所以...我想范围问题已经解决了。 但是,我的微调器没有隐藏,加载页面时看不到我的地图。 如果我导航到我的应用程序中的另一个页面,然后返回到我的地图页面,那么微调器会隐藏并且一切正常。 我的组件代码(总结)是:

      import { Component, OnInit } from '@angular/core';
      
      @Component({
          selector: 'mapa-global',
          template: `
          <div class="container" [hidden]="loaded">
              <div class="preloader-wrapper active" id="loader">
                  <div class="spinner-layer spinner-red-only">
                  <div class="circle-clipper left">
                      <div class="circle"></div>
                  </div><div class="gap-patch">
                      <div class="circle"></div>
                  </div><div class="circle-clipper right">
                      <div class="circle"></div>
                      </div>
                  </div>
              </div>   
            </div>
      
          <div id="map-canvas-container" [hidden]="!loaded">
              <div id="map-canvas"></div>   
          </div>
          `,
          styleUrls: ['./mapa.component.css']
      })
      export class MapaComponent implements OnInit {
      
          public loaded: boolean = false;
          private latitude: number = -31.7413;
          private longitude: number = -60.5115;
          private bounds: any = new google.maps.LatLngBounds();
          private zoom: number = 12;
          map: any;
      
          ngOnInit() { this.initMap(); }
      
          initMap() {
              this.map = new google.maps.Map(document.getElementById('map-canvas'), {
                  center: { lat: this.latitude, lng: this.longitude },
                  zoom: this.zoom
              });
      
              console.log("THIS OUTSIDE listener callback:", this)
              google.maps.event.addListenerOnce(this.map, 'idle', function () {
                  this.loaded = true;
                  console.log("THIS INSIDE listener callback:", this)
              }.bind(this));
          }
      }
      

      有什么建议吗?也许 [hidden] 指令的实现方式不对?

      【讨论】:

        猜你喜欢
        • 2015-11-23
        • 2010-12-05
        • 1970-01-01
        • 1970-01-01
        • 2014-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        相关资源
        最近更新 更多