如何访问另一个组件中定义的地图?

How to access a map defined in another component?

我目前正在使用 Leaflet 地图(使用 vue2leaflet)。

我做的很标准:

所以基本上我的 Map.vue 调用地图:

<v-map ref="map" :zoom="zoom" :center="center">
    <v-tilelayer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></v-tilelayer>
    <v-marker-cluster :options="clusterOptions">
        <v-marker v-for="(marker, index) in markers"
            :key="index"
            :lat-lng="makeCoords(marker.location.lat, marker.location.lng)"
                v-on:l-click="showSpot(marker._id, marker.slug, marker.location.lat, marker.location.lng)">
        </v-marker>
    </v-marker-cluster>
</v-map>

标记 来自商店 ($store.map.markers):

computed: {
    markers () {
        return this.$store.state.map.markers
    }
}

所以在同一个模板中,如果我想获得对地图的引用,我只需要这样做:

this.$refs.map

但我需要从另一个文件做同样的事情(假设“AddMarker.vue”,以便使用此方法在地图上放置新标记:

L.marker([datas.location.lat, datas.location.lng]).addTo(mymap);

其中"mymap"应该是Map.vue

中定义的对象

当然,由于地图不在同一个文件中,this.$refs.map结果为"undefined".

我试图在商店中添加地图引用,但它不起作用并引发错误(调用堆栈),我猜它不是用来存储组件的。

我尝试只在商店中提交新标记,但地图不会神奇地适应并添加它。我想我真的需要为此调用 addTo() 方法。

这是商店:

export const state = () => ({
    markers: null
})

export const mutations = {
    setMarkers(state, markers) {
        state.markers = markers
    },

    addMarker(state, marker) {
        state.markers.push(marker)
    }
}

export const actions = {
    async init({ commit }) {
        let { data } = await this.$axios.get(process.env.api.spots)
        commit('setMarkers', data)
    }
}

我是这样称呼突变的:

    that.$store.commit('map/addMarker', {
            title: values.title,
            description: values.description,
            location: {
                city: that.$store.state.position.infos.city,
                country: that.$store.state.position.infos.country,
                lat: that.$store.state.position.coords.lat,
                lng: that.$store.state.position.coords.lng
            }
        });

商店中完美添加了标记,但地图上没有任何反应。

如果有人知道如何处理这个? 谢谢!

您的实际问题是:"how do I add another marker to markers?"如果您将 markers 定义为基于商店的计算,则需要向商店添加标记。

Vue.component('v-map', Vue2Leaflet.Map);
Vue.component('v-tilelayer', Vue2Leaflet.TileLayer);
Vue.component('v-marker', Vue2Leaflet.Marker);

const store = new Vuex.Store({
  state: {
    markers: [
      [47.42, -1.25],
      [47.41, -1.21],
      [47.43, -1.22]
    ].map(p => L.latLng(...p))
  },
  mutations: {
    addMarker(state, payload) {
      state.markers.push(payload);
    }
  },
  actions: {
    addMarker({
      commit
    }, payload) {
      commit('addMarker', payload)
    }
  }
})

const v = new Vue({
  el: '#app',
  store,
  data() {
    return {
      zoom: 13,
      center: [47.413220, -1.219482],
      url: 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
      attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
    }
  },
  computed: {
    markers() {
      return this.$store.state.markers;
    }
  }
});

setTimeout(() => {
  store.dispatch('addMarker', L.latLng(47.412, -1.24));
}, 1400);
html,
body,
#app {
  height: 100%;
  margin: 0;
}
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<script src="//unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
<script src="//unpkg.com/vue2-leaflet@0.0.57/dist/vue2-leaflet.js"></script>
<script src="//unpkg.com/vuex@latest/dist/vuex.js"></script>
<link href="//unpkg.com/leaflet@1.0.3/dist/leaflet.css" rel="stylesheet" />
<div id="app">
  <v-map :zoom="zoom" :center="center">
    <v-tilelayer :url="url" :attribution="attribution"></v-tilelayer>
    <v-marker v-for="marker in markers" :lat-lng="marker"></v-marker>
  </v-map>
</div>

针对这种情况考虑使用事件总线;你有可以在地图上添加标记的组件,比如说地址列表,当你点击其中一个时,一个图钉就会掉到它的位置。

// bus.js
import Vue from 'vue';
export const EventBus = new Vue();

// address-list.js
import { EventBus } from './bus.js';

methods: {
   onClick () {
      EventBus.$emit('add-marker', {x:123,y:345});
   }
}

// map.js
import { EventBus } from './bus.js';

EventBus.$on('add-marker', coords => {
   this.addMarker(coords).then(() => this.redrawMap())
});

简单明了,代码不多。作为全局总线,显然您可以在任何必要的组件中重复使用。