Angular 6-如果导入BrowserAnimationsModule(Openlayers),则会出现渲染问题

时间:2018-08-14 09:56:34

标签: angular openlayers angular6 lifecycle angular-animations

我基本上有一个渲染小地图的应用程序。在此页面上还有一个“切换”按钮,该按钮隐藏在父组件中带有* ngIf的小地图,而以大地图显示。 如果现在我将app.module.ts中的BrowserAnimationsModule导入,则在单击切换按钮时不呈现大地图(仅当我在map-base.component.ts的ngOnInit中创建地图之前将超时设置为1毫秒时)。

对不起..有点难以解释,这是代码:

App.module.ts

<c:set var="isString"><%= metric.isString(alertVal) %></c:set>                                                  
<c:when test="${isString or (metric.name eq 'something1') or (metric.name eq 'something2')}">
</c:when>

app.component.ts

...
@NgModule({
  declarations: [
    AppComponent,
    MapSmallComponent,
    MapLargeComponent,
    MapBaseComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    BrowserAnimationsModule, // comment this line, to make the app work
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

map-base.component.ts

@Component({
  selector: 'app-root',
  template: `
  <app-map-small *ngIf="small"></app-map-small>
  <app-map-large *ngIf="!small"></app-map-large>
  <button (click)="small = !small">Toggle</button>`,
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  small = true;
}

map-small.component.ts

@Component({
  selector: 'app-map-base',
  template: `<div id="map" class="map"></div>`,
  styleUrls: ['./map-base.component.scss']
})
export class MapBaseComponent implements OnInit {
  map: OlMap;
  constructor() { }

  ngOnInit() {
    this.map = new OlMap({
      target: 'map',
      layers: [new OlTileLayer({ source: new OlOSM() })],
      view: new OlView({ zoom: 13, center: fromLonLat([13.376935, 52.516181]) }),
      controls: []
    });
  }
}

map-large.component.ts

@Component({
  selector: 'app-map-small',
  template: `
    <p>other stuff</p>
    <div style="max-width:500px">
      <app-map-base></app-map-base>
    </div>
    <p>other stuff2</p>
  `,
  styleUrls: ['./map-small.component.scss']
})
export class MapSmallComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
}

依赖项

@Component({
  selector: 'app-map-large',
  template: `
  <p>Some other stuff</p>
  <app-map-base></app-map-base>`,
  styleUrls: ['./map-large.component.scss']
})
export class MapLargeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }
}

那么,如果我不导入BrowserAnimationsModule,并且导入失败,为什么一切正常?我想使用Angular Material,那是我需要的...

3 个答案:

答案 0 :(得分:1)

这是一个解决方案,

组件模板

<div #mapElementRef class="map"></div>

Component类实现OnInit并具有下一个属性

@ViewChild('mapElementRef') mapElementRef: ElementRef;

最终通过ngOnInit方法初始化地图,您可以使用

this.map.setTarget(this.mapElementRef.nativeElement);

希望有帮助。

答案 1 :(得分:0)

您必须使用ngAfterViewInit,然后才能“确保”组件模板中的元素存在于DOM中。

ngAfterViewInit() {
  this.map = new OlMap({
    target: 'map',
    layers: [new OlTileLayer({ source: new OlOSM() })],
    view: new OlView({ zoom: 13, center: fromLonLat([13.376935, 52.516181]) }),
    controls: []
  });
}

答案 2 :(得分:0)

注意脏修复
我确实尝试过@cabesuon 的版本,但它仍然无法正常工作。

就像@cabueson 说的,做

<div #mapElementRef class="map"></div>

然后在您的 component.ts 中,但是

  • ngAfterViewInit()下将其婴儿化正如@PoulKrujit所说
  • 添加 setTimeout(() => {}) 这是肮脏的修复

结果如下

export class MapBaseComponent implements AfterViewInit {
  @ViewChild('mapElementRef', { static: true }) mapElementRef: ElementRef

  map: OlMap

  constructor() {}

  ngAfterViewInit() {
    setTimeout(() => {
      this.map = new Map({
        layers: [new OlTileLayer({ source: new OlOSM() })],
        view: new OlView({ zoom: 13, center: fromLonLat([13.376935, 52.516181]) }),
        controls: [],
      })

      this.map.setTarget(this.mapElementRef.nativeElement)
    }, 0)
  }
}

我不是 100% 确定为什么,但这是我的猜测。
ion-content 一旦实例化就不会刷新自己。但是,将代码置于超时强制离子内容被刷新。这也是为什么您不必放置任何毫秒的原因。

确实存在强制 ionic 应用程序刷新的其他方法,例如 tick,但超时对于我们在这里所做的事情来说已经足够了。