【问题标题】:Creating map using Leaflet & Vue.js使用 Leaflet 和 Vue.js 创建地图
【发布时间】:2020-03-27 11:09:05
【问题描述】:

我正在尝试使用 Leaflet 和 Vue 组件创建地图。出于某种原因,“中心:”属性不接受我的纬度和经度数组坐标?当我在模板 html {{ latlng }} 中使用它时,我得到一个具有正确坐标的数组。任何帮助将不胜感激。

<template>
  <div id="mapContainer">{{ latlng }}</div>
</template>

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


export default {
  name: "Map",
  data() {
    return {
      map: null,
      latlng: []
    };
  },
  methods: {
    get_lat_lng: function(){
        axios.get('http://127.0.0.1:5000/api/get_latitude')
            .then(res => this.latlng.push(res.data))
        axios.get('http://127.0.0.1:5000/api/get_longitude')
            .then(res => this.latlng.push(res.data))
    }
  },
  created: function(){
      this.get_lat_lng()
  },
  mounted() {

    this.map = L.map("mapContainer", {
        center: this.latlng,
        zoom: 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: 50vw;
  height: 50vh;
}
</style>

【问题讨论】:

  • 可能是在 axios 异步调用完成之前调用了mounted() 方法。你需要稍微改变你的逻辑,所以地图不是在挂载时创建,而是在 axios 完成时创建。
  • 我尝试将 axios 调用直接放在 created() 中。根据生命周期图,created 在mounted 之前运行。不太确定这里发生了什么。
  • 调用顺序大概就是这个1.created(), 2.mounted(), 3.axios.then()。
  • 所以需要在axios.then()调用中初始化地图

标签: javascript vue.js leaflet


【解决方案1】:

您在此处遇到了比赛条件。 mounted() 钩子在 axios.get 异步调用完成之前被调用。

调用顺序大概是这样 1.created(), 2.mounted(), 3.axios.then()

因此,您需要稍微更改逻辑,以便在创建完成并调用挂载挂钩时初始化地图。

这样的,

为已执行的挂载调用添加标志

data() {
  return {
    map: null,
    mounted: false,
    latlng: null
  }

将地图创建代码移到方法中

createMap: function() {
  this.map = L.map("mapContainer", { center: this.latlng ...

在创建时获取数据,如果已经挂载,则创建地图

created(){
  axios.all([axios.get('http://127.0.0.1:5000/api/get_longitude');
             axios.get('http://127.0.0.1:5000/api/get_latitude')])
    .then((longresp,latresp)=> {
       this.latlng=[latresp.data,longresp.data];
       if (this.mounted) this.createMap()
     })

然后在mounted时,偶然检查数据是否已经可用,如果没有,设置创建地图的标志

mounted() {
 if (this.latlng) this.createMap()
 this.mounted = true;
 ...

【讨论】:

  • 这应该是我选择的答案。非常容易理解,而且这也保持了与 API 的兼容性。
  • 谢谢 PA。很有帮助。
【解决方案2】:

数据可用时创建 Map(当 axios promise 成功时)。

更多关于承诺:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

在内容未准备好之前使用指示器。

我认为不需要单独的请求,所以我合并了 2 个 axios 请求。您的后端应该返回 [lat, long] 数组。

<template>
    <div>
        <!--
         I also added a simple loading indicator,
         obviously you can go for something more fancy like a spinner
        --!>
        <p v-if="loading">Loading...</p>
        <div id="mapContainer">{{ latlng }}</div>
    </div>
</template>

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

    export default {
        name: "Map",
        data() {
            return {
                map: null,
                loading: false,
                latlng: []
            };
        },
        methods: {
            setupLeafletMap: function () {

                this.map = L.map("mapContainer", {
                    center: this.latlng,
                    zoom: 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);

            }
        },
        mounted() {

            this.loading = true;

            axios.get('http://127.0.0.1:5000/api/get_latlng').then(res => {

                this.latlng = res.data;
                this.setupLeafletMap();  // Creating the Map here ensures that data is already loaded from server side

                this.loading = false;

            }).catch(error => console.error(error));

        },
        beforeDestroy() {
            if (this.map) {
                this.map.remove();
            }
        }
    };
</script>

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

【讨论】:

  • 我很高兴这对您有所帮助! PA的回答更详细一点,也保持API兼容性请选择那个。
猜你喜欢
  • 2021-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-14
  • 1970-01-01
  • 2022-08-03
相关资源
最近更新 更多