如何访问另一个组件中定义的地图?
How to access a map defined in another component?
我目前正在使用 Leaflet 地图(使用 vue2leaflet)。
我做的很标准:
- 地点列表是从应用商店 (vuex) 中的 REST Api 导入的
- 然后在地图初始化时,使用商店中的这些信息生成标记
所以基本上我的 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: '© <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())
});
简单明了,代码不多。作为全局总线,显然您可以在任何必要的组件中重复使用。
我目前正在使用 Leaflet 地图(使用 vue2leaflet)。
我做的很标准:
- 地点列表是从应用商店 (vuex) 中的 REST Api 导入的
- 然后在地图初始化时,使用商店中的这些信息生成标记
所以基本上我的 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: '© <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())
});
简单明了,代码不多。作为全局总线,显然您可以在任何必要的组件中重复使用。