Ionic-Vue项目中传入GeoJSON为props时如何更新Mapbox地图标记
问题根因
你代码里存在6处核心错误,直接导致标记不加载、不更新:
- Home.vue模板绑定的prop值和计算属性名不匹配,子组件根本拿不到正确的GeoJSON数据
- Mapbox load事件回调用普通函数声明,
this指向丢失,无法正确读取props和调用实例方法 addMarkers方法中遍历features用普通函数,this指向丢失,无法读取地图实例- 没有监听
markersprop的变化,父组件更新数据后子组件无感知 - 没有做
markers非空兼容,数据为undefined时直接调用.features会抛出隐式报错 - 没有清理旧标记的逻辑,后续数据更新会导致标记重复叠加
修复步骤
1. 修复Home.vue绑定错误
把模板里的:markers="geojson"改成和计算属性名一致的:markers="getGeoJson":
<template> <the-map :markers="getGeoJson" @updatedLocation="updateMap"></the-map> </template>
2. 修复TheMap.vue逻辑
修改后的完整script代码如下:
export default { props: ["markers"], emits: ["updatedLocation"], data() { return { access_token: process.env.VUE_APP_MAP_ACCESS_TOKEN, center: [0, 0], map: null, markerList: [] // 存储生成的标记实例,用于后续清理 }; }, watch: { // 监听markers变化,自动更新标记 markers(newVal) { // 地图没初始化完直接返回 if (!this.map || !this.map.isStyleLoaded()) return // 清理旧标记 this.markerList.forEach(marker => marker.remove()) this.markerList = [] // 非空判断 if (!newVal || !newVal.features) return // 更新Mapbox源数据 if (this.map.getSource('places')) { this.map.getSource('places').setData(newVal) } else { this.map.addSource("places", { type: "geojson", data: newVal }) } // 重新生成标记 this.addMarkers() } }, mounted() { this.createMap(); }, methods: { async createMap() { try { const coords = await Geolocation.getCurrentPosition(); this.center = [coords.coords.longitude, coords.coords.latitude]; mapboxgl.accessToken = this.access_token; //Map Instance this.map = new mapboxgl.Map({ container: "map", style: "mapbox://styles/userName/API_KEY", center: this.center, zoom: 12, scrollZoom: true, }); // Custom Attribution over the map for Branding this.map.addControl( new mapboxgl.AttributionControl({ customAttribution: ` © Comapny Name`, }) ); // 改成箭头函数修正this指向 this.map.on("load", () => { // 初始化时如果有markers直接加载 if (this.markers && this.markers.features) { this.map.addSource("places", { type: "geojson", data: this.markers, }); this.addMarkers(); } }); const UserLocationMarker = new mapboxgl.Marker({ draggable: true, }) .setLngLat(this.center) .addTo(this.map); UserLocationMarker.on("dragend", async (e) => { this.center = Object.values(e.target.getLngLat()); this.$emit("updatedLocation", this.center); }); } catch (err) { console.log(err); } }, addMarkers() { // 改成箭头函数修正this指向 this.markers.features.forEach(marker => { var el = document.createElement("div"); el.id = "marker-" + marker.properties.id; el.className = "marker"; const newMarker = new mapboxgl.Marker(el, { offset: [0, -23] }) .setLngLat(marker.geometry.coordinates) .addTo(this.map); // 把标记实例存到数组里方便后续清理 this.markerList.push(newMarker) }); }, }, };
内容的提问来源于stack exchange,提问作者Nishant S Vispute
相关产品推荐
相关产品推荐

