开发者问题收集

Vuejs Leaflet:未找到地图容器

2018-08-27
9449

我正在尝试在 Vue 中使用 Leaflet 地图,但一直出现错误:

Uncaught Error: Map container not found.

这是我的组件的样子:

<template>
  <div id="app" class="container">
    Map
    <div class="col-md-9">
      <div id="mapid"></div>
    </div>
  </div>
</template>

<style scoped>
#mapid { 
    height: 800px;
}
</style>

<script>
import L from 'leaflet'

var mymap = L.map('mapid').setView([51.505, -0.09], 13);

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={}', {
    attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    maxZoom: 18,
    id: 'mapbox.streets',
    accessToken: ''
}).addTo(mymap);
</script>

我还在我的 index.html 头中添加了 Leaflet CSS 和 JavaScript。

1个回答

欢迎来到 SO!

当您尝试 通过传递您的元素 id ( L.map('mapid') ) 来实例化您的 Leaflet Map 时,问题是您的 Vue 组件尚未附加到您的页面 DOM。因此,当 Leaflet 尝试查询后者以查找您的元素时,它找不到它,因此出现错误消息。

如果您尝试在 mounted 生命周期钩子中实例化,也会发生同样的事情:您的 Vue 组件实例已创建并且其片段 HTML 结构已构建,但仍未附加到页面 DOM。

但是,您可以直接传递元素,而不是传递元素 id。请注意,您仍然需要在 mounted 钩子中执行此操作,以确保您的组件实例确实具有构建的 HTML 结构。

L.map(<HTMLElement> el, <Map options> options?)

Instantiates a map object given an instance of a <div> HTML element and optionally an object literal with Map options .

然后要获取您的元素,只需利用 Vue $refs 实例属性和 ref 特殊属性,如 Vue 指南 > 中所述 访问子组件实例 &子元素

[…] sometimes you might still need to directly access a child component in JavaScript. To achieve this you can assign a reference ID to the child component using the ref attribute.

因此,在您的情况下,您的模板中应该有:

<div id="mapid" ref="mapElement"></div>

在您的组件脚本中:

import L from 'leaflet'

export default {
  mounted() {
    var mymap = L.map(this.$refs['mapElement']).setView([51.505, -0.09], 13);
    // etc.
  },
}

使用 Vue ref 而不是 HTML id 的额外优势是,您可以拥有多个具有自己地图的 Vue 组件实例,并且 Vue 将引用每个脚本的相应元素。

而使用 HTML id,如果您有多个具有相同 id 的地图元素,每次您尝试实例化地图时,Leaflet 只会获取第一个,从而引发错误,提示该容器的地图已初始化。

ghybs
2018-08-28