切换另一个组件的地图图层可见性



首先,我是设计专业的学生,我使用 Vue.js 来制作我的高级项目的原型。所以这不是真正的工作项目。只是一些日记应用程序的原型。

我的问题是,我通过具有瓦片层的 Vue2Leaflet 构建了一个地图组件。

在图块层上,我渲染了一个GeoJSON文件,该文件有两个坐标对象。

我还有一个日期选择器组件,它通过事件总线发出值。

我的目标是:当日期选择器发出特定值时,关闭一个<l-geo-json>并打开另一个<l-geo-json>

<l-geo-json>有一个:visible显示或隐藏的参数。:visible从 GeoJSON 对象获取参数。datepicker发出一些布尔值来更改 GeoJSON 参数。GeoJSON 参数会更改,但它不会在地图中呈现。

我认为,这是因为没有重新渲染地图组件。

我的地图组件是这样的:

<template>
<div v-if="refresh" id="MapView2">
<i class="material-icons geoLocate" v-on:click="geoLoc">location_searching</i>
<l-map :zoom="zoom" :options="{ zoomControl: false }" class="map" :center="center">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-geo-json :visible="yesterday.day" :geojson="bus.geojson" :options="bus.options"></l-geo-json>
<l-geo-json :visible="today.day" :geojson="today.geojson" :options="today.options"></l-geo-json>
</l-map>
</div>
</template>
<script>
import Vue from 'vue';
import Leaflet from 'leaflet';
import L from 'leaflet';
import { LMap, LTileLayer, LGeoJson } from 'vue2-leaflet';
import PopupContent from './GeoJson2Popup';
import { data, EventBus2 } from '../assets/geojson/sample-geojson.js';

export default {
name: 'MapView2',
components: {
LMap,
LTileLayer,
LGeoJson,
},
data(){
return {
zoom: 13,
center: {
lat: '',
lng: '',
},
url:'https://api.mapbox.com/styles/v1/mapbox/light-v9/tiles/256/{z}/{x}/{y}?access_token=...',
attribution: '',
yesterday: {
geojson: data.yesterday,
day: data.yesterday.visible,
options: {
onEachFeature: onEachFeature,
color: "#45B8FF",
fillOpacity: 0.8
}
},
today: {
geojson: data.today,
day: data.today.visible,
options: {
onEachFeature: onEachFeature,
color: "#45B8FF",
fillOpacity: 0.8
}
},
}
},
methods: {
geoLoc() {
navigator.geolocation.getCurrentPosition(position => {
this.position = position.coords;
this.center.lat = position.coords.latitude
this.center.lng = position.coords.longitude
this.zoom = 25
console.log(position.coords)
})
}
},
beforeCreate() {
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(position => {
this.isLoading = false
this.position = position.coords;
this.center.lat = position.coords.latitude
this.center.lng = position.coords.longitude
console.log(position.coords)
})
}
},
mounted() {
EventBus2.$on('mapDay', pickerValue => {
switch (pickerValue) {
case data.today.id:
data.yesterday.visible = true;
data.today.visible = false;
break;
case data.yesterday.id:
data.yesterday.visible = false;
data.today.visible = true;
break;
}
});
},
};
</script>

还有我的 geojson.js 文件就像

import Vue from 'vue';
export const EventBus2 = new Vue();
export const data = {
today: {
"type": "FeatureCollection",
"id": "0520",
"visible": false,
"features": [ // geojson features and coordinates ]
},
yesterday: {
"type": "FeatureCollection",
"id": "0520",
"visible": false,
"features": [ // geojson features and coordinates ]
}
}

如您所见,日期选取器以MMDD格式发出一些值。Switch 语句按id检查 GeoJSON 数据中的值。如果匹配,请更改visible属性。当日期选取器发出时,它实际上会发生变化。

但它不会在地图中呈现(GeoJSON 图层不会相应地更改可见性(。

我该怎么做?我应该使用watch或类似的东西吗?如果是,我该如何使用它?

您应该直接更改实例data

为了清楚起见,我将像您从geojson.js文件中导入一样data2.称两者相同可能是您感到困惑的原因。

import { data as data2, EventBus2 } from '../assets/geojson/sample-geojson.js';

GeoJSON 图层可见性不会动态更改的原因是,您使用data2中的信息正确初始化实例dataday属性,但这不会将它们动态绑定到data2中的未来修改。

因此,最简单的方法是在"mapDay"事件侦听器中切换实例dataday属性,而不是data2中的信息。

EventBus2.$on('mapDay', pickerValue => {
switch (pickerValue) {
case data2.today.id:
this.yesterday.day = true;
this.today.day = false;
break;
case data2.dun.id:
this.yesterday.day = false;
this.today.day = true;
break;
}
});

您还可以切换datadata2,以防您希望data2也同步,例如,如果您在另一个组件中使用它。请注意,这样的策略是脆弱的,因为更改其他组件中的data2在这里不会有任何影响。

另一方面,您可以通过简单地将pickerValue存储在实例data中来简化可见性切换逻辑,并将其与属性绑定表达式中的geojson.id进行比较:visible:visible="pickerValue === yesterday.geojson.id"

代码示例:

Vue.component('map-view-2', {
template: '#map-view-2',
components: {
'l-map': Vue2Leaflet.LMap,
'l-tile-layer': Vue2Leaflet.LTileLayer,
'l-geo-json': Vue2Leaflet.LGeoJson,
},
data() {
return {
pickerValue: '0520',
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
yesterday: {
geojson: data2.yesterday,
},
today: {
geojson: data2.today,
},
};
},
mounted() {
this.$root.$on('mapDay', pickerValue => {
this.pickerValue = pickerValue;
});
},
});
// Dummy DatePicker component for the sake of the demo.
Vue.component('date-picker', {
template: '#datepicker',
methods: {
handleInputChange(event) {
this.$root.$emit('mapDay', event.target.value);
},
},
});
const data2 = {
today: {
"type": "FeatureCollection",
"id": "0520",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.34, 48.86] // Left
},
}],
},
yesterday: {
"type": "FeatureCollection",
"id": "0519",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.35, 48.86] // Right
},
}],
},
};
new Vue({
el: '#app',
});
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js"></script>
<script src="https://unpkg.com/vue2-leaflet@1.0.2/dist/vue2-leaflet.js"></script>
<template id="map-view-2">
<div id="MapView2">
<l-map :zoom="11" style="height: 100px;" :center="[48.86, 2.35]">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-geo-json :visible="pickerValue === yesterday.geojson.id" :geojson="yesterday.geojson"></l-geo-json>
<l-geo-json :visible="pickerValue === today.geojson.id" :geojson="today.geojson"></l-geo-json>
</l-map>
</div>
</template>
<template id="datepicker">
<fieldset @change="handleInputChange">
<legend>Choose a date</legend>
<input type="radio" name="date" value="0520" id="today" checked />
<label for="today">Today 0520</label>
<input type="radio" name="date" value="0519" id="yesterday" />
<label for="yesterday">Yesterday 0519</label>
<input type="radio" name="date" value="none" id="none" />
<label for="none">None</label>
</fieldset>
</template>
<div id="app">
<map-view-2></map-view-2>
<date-picker></date-picker>
</div>

一种更模块化的方法会将pickerValue数据公开为prop,以便您直接在父级(例如 App(级别对其进行修改,而不必侦听您的"mapDay"事件:

Vue.component('map-view-2', {
template: '#map-view-2',
components: {
'l-map': Vue2Leaflet.LMap,
'l-tile-layer': Vue2Leaflet.LTileLayer,
'l-geo-json': Vue2Leaflet.LGeoJson,
},
props: {
// Receive the value directly from parent component / App.
pickerValue: {
type: String,
default: '0520',
},
},
data() {
return {
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
yesterday: {
geojson: data2.yesterday,
},
today: {
geojson: data2.today,
},
};
},
});
// Dummy DatePicker component for the sake of the demo.
Vue.component('date-picker', {
template: '#datepicker',
props: {
value: {
type: String,
default: '0520',
},
},
methods: {
handleInputChange(event) {
// https://vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model
this.$emit('input', event.target.value);
},
},
});
const data2 = {
today: {
"type": "FeatureCollection",
"id": "0520",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.34, 48.86] // Left
},
}],
},
yesterday: {
"type": "FeatureCollection",
"id": "0519",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.35, 48.86] // Right
},
}],
},
};
new Vue({
el: '#app',
data() {
return {
pickerValue: '0519', // This value rules child components default value.
};
},
});
<script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js"></script>
<script src="https://unpkg.com/vue2-leaflet@1.0.2/dist/vue2-leaflet.js"></script>
<template id="map-view-2">
<div id="MapView2">
<l-map :zoom="11" style="height: 100px;" :center="[48.86, 2.35]">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-geo-json :visible="pickerValue === yesterday.geojson.id" :geojson="yesterday.geojson"></l-geo-json>
<l-geo-json :visible="pickerValue === today.geojson.id" :geojson="today.geojson"></l-geo-json>
</l-map>
</div>
</template>
<template id="datepicker">
<fieldset @change="handleInputChange">
<legend>Choose a date</legend>
<input type="radio" name="date" value="0520" id="today" :checked="value === '0520'" />
<label for="today">Today 0520</label>
<input type="radio" name="date" value="0519" id="yesterday" :checked="value === '0519'" />
<label for="yesterday">Yesterday 0519</label>
<input type="radio" name="date" value="none" id="none" :checked="value === 'none'" />
<label for="none">None</label>
</fieldset>
</template>
<div id="app">
<map-view-2 :picker-value="pickerValue"></map-view-2>
<date-picker v-model="pickerValue"></date-picker>
</div>

话虽如此,如果你的工作只是为了设计原型,甚至没有炫耀你的编程技能,那么即使是 Vue,虽然已经很简单,但对于你的任务来说也可能是矫枉过正的。

最新更新