无法在Vue组件内加载Leaflet

时间:2017-03-15 17:16:34

标签: leaflet vue.js vuejs2

我正在尝试创建一个Leaflet地图作为Vue组件,但我有一些困难的入门。我通过npm

安装了Leaflet

我哪里错了? console.log(Leaflet)正在返回一个Leaflet对象,但我无法让地图展开和渲染。

有些方向值得赞赏

<template>
    <div id="map"></div>
</template>

<script>
    // import leaflet here?
    import Leaflet from 'leaflet';

    export default {
        components: {
            Leaflet
        },

        created() {
            console.log(this);
            console.log(Leaflet);
        },

        ready() {
            this.map = L.map('map').setView([51.959, -8.623], 14);
            L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
                attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            }).addTo(this.map);
        }
    }
</script>

<style>
    #map {
        height: 100%;
        width: 100%;
        margin-top: -24px;
    }

    /* default legend, layer styling from leaflet template */
    .info {
        padding: 6px 8px;
        font: 14px/16px Arial, Helvetica, sans-serif;
        background: white;
        background: rgba(255,255,255,0.8);
        box-shadow: 0 0 15px rgba(0,0,0,0.2);
        border-radius: 5px;
    }
    .info h4 {
        margin: 0 0 5px;
        color: #777;
    }
    .legend {
        text-align: left;
        line-height: 18px;
        color: #555;
    }
    .legend i {
        width: 18px;
        height: 18px;
        float: left;
        margin-right: 8px;
        opacity: 0.7;
    }
</style>

3 个答案:

答案 0 :(得分:1)

您的代码中有几个问题:

  1. Vue中没有ready生命周期挂钩。使用mounted()
  2. 您正试图将Leaflet库作为组件传递给Vue,由于Leaflet不是Vue组件,并且不需要在Vue中进行任何注册,因此它什么也不做。
  3. 未在Vue组件上声明map数据属性。
  4. 将库导入为Leaflet from 'leaflet'并没有问题,但是您自己或其他人将Leaflet对象声明为L from 'leaflet'可能会更加一致。您还可以使用:import { Map } from 'leaflet',但是必须适当地初始化地图:this.map = new Map("mapContainer")
  5. 通过在Leaflet Map类上使用remove()方法来适当地防止潜在的内存泄漏和/或清理。 Vue beforeDestroy生命周期挂钩内是一个好地方。

此外,不要忘记导入Leaflet CSS,例如: import "leaflet/dist/leaflet.css";

<template>
  <div id="mapContainer"></div>
</template>

<script>
import "leaflet/dist/leaflet.css";
import L from "leaflet";

export default {
  name: "LeafletMap",
  data() {
    return {
      map: null
    };
  },
  mounted() {
    this.map = L.map("mapContainer").setView([51.959, -8.623], 12);
    L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
      attribution:
        '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
    }).addTo(this.map);
  },
  beforeDestroy() {
    if (this.map) {
      this.map.remove();
    }
  }
};
</script>

<style scoped>
#mapContainer {
  width: 100vw;
  height: 100vh;
}
</style>

答案 1 :(得分:0)

jhickok 已经提供了正确答案,但对 vue3 组合 API 也很有见地。出于同样的原因,无法在 setup() 中实例化传单地图。

<template>
  <div id="mapContainer"></div>
</template>

<script>
import { map, tileLayer } from "leaflet";
import { onMounted, onBeforeUnmount } from "vue";

export default {
  name: "Map",
  setup() {
    let container = null;

    onMounted(() => {
      container = map("mapContainer").setView([51.959, -8.623], 12);

      tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
        attribution:
          '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(container);
    });

    onBeforeUnmount(() => {
      container.remove();
    });
  }
};
</script>

<style scoped>
#mapContainer {
  width: 40vw;
  height: 40vh;
}
</style>

答案 2 :(得分:-1)

我刚刚做了这个,但我也需要底图(bing)。

leafletWrapper.js

const L = require('leaflet')
require('leaflet-bing-layer')

export default L

LeafletMap.vue

<template>
  <div id="map">
  </div>
</template>

<script>
import L from 'leafletWrapper'

export default {
    name: 'leaflet-map',
    props: ['center', 'zoom', 'minZoom', 'maxZoom', 'markers'],
    data () {
      return {
        mapObject: {},
        markerLayer: {}
      }
    },
 mounted () {
      const bingKey = 'foo'

      this.mapObject = L.map(
        "map", {
          center: this.center,
          zoom: this.zoom,
          minZoom: this.minZoom,
          maxZoom: this.maxZoom
        }
      )

      L.tileLayer.bing({bingMapsKey: bingKey, imagerySet: 'Road'}).addTo(this.mapObject)

    },
    beforeDestroy () {
      this.mapObject.clearAllEventListeners()
    }

  }
</script>