我的VueJS项目有问题。我在DetailView.vue中创建了一个GoogleMaps组件。地图组件使用三个道具,例如driver
,waypoints
和stopOver
。
项目结构为: App.vue包含Login.vue以及到主仪表板视图的路由。 在此MainView中,我有一些菜单元素,例如“ Tours”,其中有一个DataTable。
点击数据表行,VueJS在v-dialog
内显示一个DetailView.vue(使用Vuetify)。
在这个DetailView中,还有另一个数据表,一个开关和顶部的我的地图组件。
<LiefermaxMap style="width: 100%; height: 50%;" :waypoints="waypoints" :driver="driverLocation" :stopOver="showCalculatedTour"></LiefermaxMap>
waypoints
和driverLocation
是计算属性,showCalculatedTour
是常规属性,具体取决于开关的状态。
关闭此DetailVue对话框并打开另一个导览会导致将另一组航路点(以及driverLocation也)推到该属性,而不是替换旧的路标。
waypoints() {
var points = [];
if (!this.showCalculatedTour) {
this.loadnoSpecific.items.items.forEach(element => {
var p = { lat: element.latitude, lng: element.longitude, done: element.done };
points.push(p);
});
} else {
this.data.contracts.forEach(element => {
var c = element.customer.position;
var p = { lat: c.lat, lng: c.lng, done: element.done }
points.push(p);
});
}
console.log('points: ' + points)
return points;
},
driverLocation() {
const drv = this.data.location;
const marker = { lat: drv.latitude, lng: drv.longitude };
return marker;
},
这里有一个screenshot of the project。
我做错了什么?
更新:
预期行为:从之前选择的游览中删除所有其他航路点 实际行为:航点被添加到旧航路点
Tours.vue示例(屏幕快照对话框后面的视图):
<template>
<div>
<v-toolbar flat color="white">
<v-toolbar-title>Touren</v-toolbar-title>
<v-spacer></v-spacer>
</v-toolbar>
<v-data-table style="width: 70vw;"
:headers="headers"
:items="tours.items.items"
:rows-per-page-items="[5,10,20,50,100]"
:loading="isLoading"
:total-items="totalItems"
:must-sort="true"
:pagination.sync="pagination"
class="elevation-1"
>
<template slot="items" slot-scope="props">
<tr @click="rowClicked(props.item)">
<td class="text-xs-left">{{ props.item.loadno }}</td>
<td class="text-xs-left">{{ props.item.tourname }}</td>
<td class="text-xs-left">{{ props.item.kfz }}</td>
<td class="text-xs-left">{{ props.item.driverID }}</td>
<td class="text-xs-left">{{ props.item.device }}</td>
<td class="text-xs-left">{{ props.item.created_at | formatDate }}</td>
</tr>
</template>
</v-data-table>
<v-dialog v-model="showDetail" transition="dialog-bottom-transition" max-width="70vw">
<TourDetail v-model="showDetail" :data="selectedTour" style="height: 90vh;"></TourDetail>
</v-dialog>
</div>
</template>
<script>
import { settings } from '../settings';
import { authHeader } from '../_helpers';
import TourDetail from './TourDetail.vue';
export default {
name: 'tours',
components: {
TourDetail
},
data() {
return {
totalItems: 0,
selectedTour: {},
showDetail: false,
pagination: {
descending: true,
page: 1,
rowsPerPage: 10,
sortBy: 'loadno'
},
headers: [ // .. ]
};
},
watch: {
pagination(newValue, oldValue) {
this.getDataFromApi();
},
tours(newValue, oldValue) {
this.totalItems = newValue.items.total;
}
},
mounted() {
this.getDataFromApi();
},
computed: {
tours() {
return this.$store.state.tours.all;
},
isLoading() {
return this.$store.state.tours.loading;
}
},
methods: {
rowClicked(tour) {
const requestOptions = {
method: 'GET',
headers: authHeader()
};
const loadno = tour.loadno;
console.log('LoadNo: ' + loadno);
this.$store.dispatch('locations/getLoadnoSpecific', { loadno });
fetch(
`${settings.apiUrl}/tours/loadno/complete/` + loadno,
requestOptions
).then(response =>
response.json().then(json => {
this.selectedTour = json.tour;
this.showDetail = true;
})
);
},
getDataFromApi() {
const perpage = this.pagination.rowsPerPage;
const page = this.pagination.page;
const sortby = this.pagination.sortBy;
const descending = this.pagination.descending;
this.$store.dispatch('tours/getAll', {
perpage,
page,
sortby,
descending
});
}
}
};
</script>
TourDetail.vue
<template>
<v-flex style="height: 100%;">
<v-toolbar
color="primary"
dark
flat
style="z-index: 2; position: absolute;"
>
<v-toolbar-title class="justify-center">Fahrer: {{ data.driver.firstname + ' ' + data.driver.lastname }} | iPad: {{ data.device }} | Fahrzeug: {{ data.kfz }}</v-toolbar-title>
</v-toolbar>
<v-card style="height: 100%; position: relative;">
<LiefermaxMap style="width: 100%; height: 50%;" :waypoints="waypoints" :driver="driverLocation" :stopOver="showCalculatedTour"></LiefermaxMap>
<v-layout row wrap style="height: 50%;">
<v-flex xs12>
<v-card style="height: 100%;">
<v-switch v-model="showCalculatedTour" :label="switchLabel" style="position: absolute; right: 10%;"></v-switch>
<v-data-table
:headers="headers"
:items="data.contracts"
:expand="expand"
:rows-per-page-text="perPageText"
style="padding: 5%;"
>
<template slot="items" slot-scope="props">
...
</template>
<template slot="expand" slot-scope="props">
<v-card>
<div>
...
</div>
</v-card>
</template>
</v-data-table>
</v-card>
</v-flex>
</v-layout>
</v-card>
</v-flex>
</template>
<script>
import LiefermaxMap from '../components/LiefermaxMap.vue';
export default {
components: {
LiefermaxMap
},
computed: {
loadnoSpecific() {
return this.$store.state.locations.loadnoSpecific;
},
waypoints() {
var points = [];
if (!this.showCalculatedTour) {
this.loadnoSpecific.items.items.forEach(element => {
var p = { lat: element.latitude, lng: element.longitude, done: element.done };
points.push(p);
});
} else {
this.data.contracts.forEach(element => {
var c = element.customer.position;
var p = { lat: c.lat, lng: c.lng, done: element.done }
points.push(p);
});
}
console.log('points: ' + points)
return points;
},
driverLocation() {
const drv = this.data.location;
const marker = { lat: drv.latitude, lng: drv.longitude };
return marker;
},
switchLabel() {
return this.showCalculatedTour ? 'errechnete Route' : 'gefahrene Route';
}
},
props: ['data'],
data() {
return {
showCalculatedTour: false,
googleWaypoints: [],
drivenWaypoints: [],
expand: false,
perPageText: 'pro Seite',
completeTourLoading: true,
completeTour: [{}],
selectedContract: {},
headers: [... ]
};
},
methods: { ... }
}
};
</script>
<style scoped>
// ...
</style>
和LiefermaxMap组件:
<template>
<div v-show="mapInitialized" class="liefermaxmap" id="liefermaxmap" ref="liefermaxmap"></div>
</template>
<script>
export default {
name: 'LiefermaxMap',
props: ['waypoints', 'driver', 'stopOver'],
data: function() {
return {
mapName: 'liefermaxmap',
markerCoordinates: [{}],
mapInitialized: false,
directionsService: null,
directionsDisplay: null,
vueGMap: null,
bounds: null,
markers: []
};
},
watch: {
waypoints(newValue, oldValue) {
console.log('Waypoints changed, count: ' + newValue.length);
console.log(newValue)
this.setWaypoints();
}
},
methods: {
createGoogleMaps: function() {
return new Promise((resolve, reject) => {
let gmap = document.createElement('script');
gmap.src =
'https://maps.googleapis.com/maps/api/js?key=XXXX';
gmap.type = 'text/javascript';
gmap.onload = resolve;
gmap.onerror = reject;
document.querySelector('head').appendChild(gmap);
});
},
initGoogleMaps: function() {
const localOptions = {
zoom: 4,
center: this.driver,
mapTypeId: google.maps.MapTypeId.ROADMAP,
panControl: true,
mapTypeControl: true,
mapTypeControlOptions: {
position: google.maps.ControlPosition.RIGHT_BOTTOM
},
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
},
zoomControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.LARGE,
position: google.maps.ControlPosition.RIGHT_CENTER
},
scaleControl: false,
streetViewControl: false,
streetViewControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
}
};
this.vueGMap = new google.maps.Map(
this.$refs['liefermaxmap'],
localOptions
);
// eslint-disable-next-line
var drivermarker = new google.maps.Marker({
position: new google.maps.LatLng(this.driver),
map: this.vueGMap,
icon: 'http://maps.google.com/mapfiles/ms/micons/truck.png'
});
this.directionsService = new google.maps.DirectionsService();
this.directionsDisplay = new google.maps.DirectionsRenderer();
this.directionsDisplay.setMap(this.vueGMap);
this.mapInitialized = true;
},
addMarker(latLng, color) {
let url = 'http://maps.google.com/mapfiles/ms/icons/';
url += color + '-dot.png';
let marker = new google.maps.Marker({
map: this.vueGMap,
position: latLng,
icon: {
url: url
}
});
},
setWaypoints() {
this.directionsService = new google.maps.DirectionsService();
this.directionsDisplay = new google.maps.DirectionsRenderer();
this.directionsDisplay.setMap(this.vueGMap);
var googleWaypoints = [];
this.waypoints.forEach(element => {
var pos = new google.maps.LatLng(element.lat, element.lng);
var wp = { location: pos, stopover: false };
googleWaypoints.push(wp);
console.log(element)
if (element.done == true) {
this.addMarker(pos, 'green')
} else {
this.addMarker(pos, 'red')
}
});
var i = 0;
var j = 0;
var temparray = [];
var chunk = 15;
for (i = 0, j = googleWaypoints.length; i < j; i += chunk) {
temparray = googleWaypoints.slice(i, i + chunk);
var request = {
origin: 'XXX',
destination: 'XXX',
travelMode: 'DRIVING',
optimizeWaypoints: true,
waypoints: temparray
};
this.directionsService.route(request, (result, status) => {
if (status === 'OK') {
this.directionsDisplay.setDirections(result);
console.log(result);
}
});
}
},
googleMapsFailedToLoad() {
this.vueGMap = 'Error while loading map';
}
},
mounted() {
this.initGoogleMaps();
}
};
</script>
<style scoped>
.liefermaxmap {
width: 100%;
height: 100%;
}
</style>
答案 0 :(得分:0)
key
强制安装更改
<LiefermaxMap style="width: 100%; height: 50%;" :waypoints="waypoints" :driver="driverLocation" :stopOver="showCalculatedTour"></LiefermaxMap>
到
<LiefermaxMap style="width: 100%; height: 50%;" :key="waypoints" :waypoints="waypoints" :driver="driverLocation" :stopOver="showCalculatedTour"></LiefermaxMap>
使用key
告诉vue不要重复使用组件-这样可以触发安装,
或移动您的initMap
方法。