如何访问另一个组件中定义的映射?

时间:2018-02-07 01:36:52

标签: javascript vue.js leaflet nuxt.js

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

我所做的几乎是标准的:

  • 地点列表是从应用商店中的REST Api导入的(vuex)
  • 然后在地图初始化时,使用商店中的这些信息生成标记

所以基本上我的 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

但我需要从另一个文件中做同样的事情(让我们说&#34; AddMarker.vue &#34;,以便在地图上放置新标记,使用这种方法:

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

其中&#34; mymap&#34;应该是 Map.vue

中定义的对象

当然,由于地图不在同一个文件中,这个。$ refs.map 会导致&#34; undefined&#34;。

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

我试图在商店中提交新标记,但地图不会神奇地适应并添加它。我想我真的需要为此调用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
            }
        });

标记在商店中完美添加,但地图上没有任何内容。

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

2 个答案:

答案 0 :(得分:2)

您的实际问题是:“如何向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>

答案 1 :(得分:1)

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

// 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())
});

直截了当,而不是很多代码。作为一个全球总线,显然你可以在任何必要的组件中重复使用。