开放层 5 | Angular 7 | Angular Material |地图在 angular material mat-stepper 中不起作用

OpenLayers 5 | Angular 7 | Angular Material | Map is not working inside angular material mat-stepper

我在我的组件 ts 文件中导入了 OpenLayers 地图,然后我创建了一个 div 块,其 id = map 必须在其中显示 OpenLayers 地图,但它没有。当我将 div 块 (#map) 移到 mat-stepper 块之外时,它就起作用了。

Component.ts:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

import OlMap from 'ol/Map';
import OlXYZ from 'ol/source/XYZ';
import OlTileLayer from 'ol/layer/Tile';
import OlView from 'ol/View';
import { fromLonLat } from 'ol/proj';

@Component({
  selector: 'app-sell',
  templateUrl: './sell.component.html',
  styleUrls: ['./sell.component.scss'],
})
export class SellComponent implements OnInit {
  ...

  map: OlMap;
  source: OlXYZ;
  layer: OlTileLayer;
  view: OlView;

  ...

  ngOnInit() {
    this.source = new OlXYZ({
      url: 'http://tile.osm.org/{z}/{x}/{y}.png',
    });

    this.layer = new OlTileLayer({
      source: this.source,
    });

    this.view = new OlView({
      center: fromLonLat([6.661594, 50.433237]),
      zoom: 3,
    });

    this.map = new OlMap({
      target: 'map',
      layers: [this.layer],
      view: this.view,
    });
  }

Component.html:

<mat-horizontal-stepper
  linear
  labelPosition="bottom"
  #stepper
  class="sell-form-container"
>
  <mat-step ...>
    <form ...>
      ...
      <div id="map"></div>  //<- here it does not work, map does not display
      ...
    </form>
  </mat-step>
  ...
</mat-horizontal-stepper>
<div id="map"></div> //<- here it works, map displays

Component.css:

#map {
  width: 100%;
  height: 500px;
}

我的代码有什么问题?

我认为您的问题与您尝试将 OLMap 附加到 mat-stepper 或 mat-step 的嵌入内容中的内容有关。

在组件生命周期中,子组件在父组件的 OnInit 阶段没有准备好。因为您将需要的 div 放在 mat 组件中,所以它被包含在该组件的生命周期中。

解决此问题的一种方法是使用 ngAfterViewInit 生命周期方法。在该方法中使用您的代码应该可以解决此问题。

ngAfterViewInit() {
  this.map = new OlMap({
    target: 'map',
    layers: [this.layer],
    view: this.view,
  });
}

出于潜在的好奇心,我还想介绍另一种使用组件的方法。留意嵌入的内容,如果你想要的元素在当前组件中,你应该使用 ViewChild 装饰器 select 它。否则,如果它在子组件中,请使用 ContentChild 装饰器。

// html
<mat-horizontal-stepper ...>
  <mat-step ...>
    <form ...>
      ...
      <div #myMapRef id="map"></div>
      ...
    </form>
  </mat-step>
  ...
</mat-horizontal-stepper>

// parent ts
@ContentChild('myMapRef') // <-- if it's in a child component, your case should use this
@ViewChild('myMapRef') // <-- if it's in this component, your "this is working" would use this
myMap: ElementRef;

ngAfterViewInit() {
  console.log(this.myMap); // can get the ID from the ElementRef
}

我强烈建议您实际熟悉组件生命周期的深度。这是我希望早点在学习时做的一件事 Angular。