ngx-leaflet 不通过服务检测图层更改 (Angular 6)

ngx-leaflet does not detect layer changes through a service (Angular 6)

我是 运行 Angular 6,我想动态地向传单地图添加一个图层,但是如果图层是从另一个组件修改的,我无法检测到 leafletLayers 的变化。如果从 map.component 执行图层更改,一切正常,但如果我从外部进行更改,则它不起作用:

示例:

map.component.ts

layers: Layer[];

addPolygon () {
    this.layers = [polygon([[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]])]
}

map.component.html

<div class="map"
  leaflet
  (leafletMapReady)="onMapReady($event)"
  [leafletOptions]="options"
  [leafletLayers]="layers">
</div>
<div>
  <button type="button" name="button" (click)="addPolygon()"></button>
</div>

现在一切正常,只要单击按钮,多边形就会显示出来。但是我需要那个按钮在另一个组件中(form.component.ts),所以我尝试与服务共享 addPolygon() 功能:

server.service.ts

@Injectable()
export class ServerService {
  addPolygon: Function;
}

我修改了MapComponent并添加了调用服务的构造函数

map.component.ts

export class MapComponent{
  layers: Layer[];

  constructor(private serverService: ServerService){ 
     this.serverService.addPolygon = this.addPolygon 
  };

form.component.ts

export class FormComponent implements OnInit {
  constructor(private serverService: ServerService) { }

  triggerMap() {
      this.serverService.addPolygon()
  }
}

但是如果我在 form.component.html 中的按钮上绑定 triggerMap(),则多边形不会添加到地图中。然而,控制台显示 map.component.ts 中的 addPolygon 已达到。

我什至尝试使用 NgZone,但没有任何区别。有什么建议吗?

Angular CLI:6.0.8

我想我已经了解了您的具体问题。它并不是真正特定于 Angular 或 Leaflet。我认为它更像是 Typescript 和 Javascript 的产物(或者可能是特定于 AOT 编译和 TS->JS 转译工作方式的东西)。

基本上,我认为问题是当您将 addPolygon 函数分配给服务对象时,this 上下文发生了变化。因此,this 最终成为服务的 this 而不是组件 this。结果是在我假设服务的内部创建了一个新的图层数组。您可以(某种程度上)通过在 MapComponent 中执行以下操作来确认这一点:

export class MapComponent {

  layers: Layer[] = [];
  counter = 0;

  constructor(
    private serverService: ServerService,
    private zone: NgZone
  ) {
    this.serverService.addPolygon = this.addPolygon;
  }

  options = {
      layers: [
          tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' })
      ],
      zoom: 5,
      center: latLng(42, 2)
  };


  addPolygon () {
    console.log('I am in addPolygon in MapComponent');
    this.counter++;
    console.log(`Here\'s the counter: ${this.counter}`);

    this.layers = [
        polygon( [[ 43, 3 ], [ 42, 0 ], [ 44, 1 ]] )
    ];
  }

  resetLayers () {
    console.log('Resetting layers');
    console.log(`Here\'s the counter: ${this.counter}`);
    this.layers = [];
  }

}

这里的想法是,我正在修改 addPolygon 内部的本地 counter 成员变量,然后将其打印到控制台。我还将它打印到 resetLayers 函数内部的控制台。

当我按以下顺序单击按钮时:MapComponent、Reset、FormComponent,我得到以下输出:

I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: 1
map.component.ts:44 Resetting layers
map.component.ts:45 Here's the counter: 1
map.component.ts:34 I am in addPolygon in MapComponent
map.component.ts:36 Here's the counter: NaN

MapComponent 单击将计数器从 0 递增到 1,并使用值 1 正确打印它。重置单击将打印正确的计数器值 1。但是,FormComponent 单击将打印 NaN,因为它未初始化为值,所以递增它就变成了 NaN。

为了确定此上下文用于 FormComponent 对 addPolygon 的调用,我为 AppComponent、ServerService 和 FormComponent 添加了初始化为不同值的计数器。事实证明,它使用来自 ServerService.

this 上下文调用 addPolygon

因此,我认为您的问题的解决方案是将图层数组放在 ServerServicem 中,或者使用输出绑定将事件从 FormComponent 传递到作为 MapComponent 和 FormComponent 的父组件的组件。