Skip to content

Commit 406968a

Browse files
committed
fix(GoogleMaps): avoid losing marker reference
1 parent 45e6f24 commit 406968a

1 file changed

Lines changed: 42 additions & 28 deletions

File tree

src/runtime/components/ScriptGoogleMaps.vue

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -129,31 +129,36 @@ const options = computed(() => {
129129
const ready = ref(false)
130130
131131
const map: Ref<google.maps.Map | undefined> = ref()
132-
const mapMarkers: Ref<Map<string, google.maps.marker.AdvancedMarkerElement>> = ref(new Map())
132+
const mapMarkers: Ref<Map<string, Promise<google.maps.marker.AdvancedMarkerElement>>> = ref(new Map())
133133
134134
function isLocationQuery(s: string | any) {
135135
return typeof s === 'string' && (s.split(',').length > 2 || s.includes('+'))
136136
}
137137
138138
async function createAdvancedMapMarker(_options: google.maps.marker.AdvancedMarkerElementOptions | `${string},${string}`) {
139-
const lib = await importLibrary('marker')
140-
const options = typeof _options === 'string'
141-
? {
142-
position: {
143-
lat: Number.parseFloat(_options.split(',')[0] || '0'),
144-
lng: Number.parseFloat(_options.split(',')[1] || '0'),
145-
},
146-
}
147-
: _options
148-
const mapMarkerOptions = defu(toRaw(options), {
149-
map: toRaw(map.value!),
150-
// @ts-expect-error unified API for maps and markers
151-
position: options.location,
139+
const key = hash(_options)
140+
if (mapMarkers.value.has(key))
141+
return mapMarkers.value.get(key)
142+
// eslint-disable-next-line no-async-promise-executor
143+
const p = new Promise<AdvancedMarkerElement>(async (resolve) => {
144+
const lib = await importLibrary('marker')
145+
const options = typeof _options === 'string'
146+
? {
147+
position: {
148+
lat: Number.parseFloat(_options.split(',')[0] || '0'),
149+
lng: Number.parseFloat(_options.split(',')[1] || '0'),
150+
},
151+
}
152+
: _options
153+
const mapMarkerOptions = defu(toRaw(options), {
154+
map: toRaw(map.value!),
155+
// @ts-expect-error unified API for maps and markers
156+
position: options.location,
157+
})
158+
resolve(new lib.AdvancedMarkerElement(mapMarkerOptions))
152159
})
153-
const marker = new lib.AdvancedMarkerElement(mapMarkerOptions)
154-
// create new marker
155-
mapMarkers.value.set(hash(_options), marker)
156-
return marker
160+
mapMarkers.value.set(key, p)
161+
return p
157162
}
158163
159164
const queryToLatLngCache = new Map<string, google.maps.LatLng>()
@@ -255,14 +260,18 @@ onMounted(() => {
255260
const toAdd = new Set([...nextMap.keys()].filter(k => !mapMarkers.value.has(k)))
256261
// do a diff of next and prev
257262
const centerHash = hash({ position: options.value.center })
258-
toRemove.forEach((key) => {
263+
for (const key of toRemove) {
259264
if (key === centerHash) {
260-
return
265+
continue
261266
}
262-
// @ts-expect-error broken type
263-
mapMarkers.value.get(key)?.setMap(null)
264-
mapMarkers.value.delete(key)
265-
})
267+
const marker = await mapMarkers.value.get(key)
268+
if (marker) {
269+
// @ts-expect-error broken type
270+
marker.setMap(null)
271+
// make sure it gets removed from map
272+
mapMarkers.value.delete(key)
273+
}
274+
}
266275
for (const k of toAdd) {
267276
// @ts-expect-error broken
268277
createAdvancedMapMarker(nextMap.get(k))
@@ -271,7 +280,7 @@ onMounted(() => {
271280
immediate: true,
272281
deep: true,
273282
})
274-
watch([() => props.center, ready], async (next, prev) => {
283+
watch([() => options.value.center, ready, map], async (next, prev) => {
275284
if (!map.value) {
276285
return
277286
}
@@ -296,7 +305,6 @@ onMounted(() => {
296305
}
297306
}, {
298307
immediate: true,
299-
deep: true,
300308
})
301309
onLoaded(async (instance) => {
302310
mapsApi.value = await instance.maps as any as typeof google.maps // some weird type issue here
@@ -398,8 +406,14 @@ const rootAttrs = computed(() => {
398406
399407
const ScriptLoadingIndicator = resolveComponent('ScriptLoadingIndicator')
400408
401-
onBeforeUnmount(() => {
402-
mapMarkers.value.forEach(marker => marker.remove())
409+
onBeforeUnmount(async () => {
410+
await Promise.all([...mapMarkers.value.entries()].map(async (_marker) => {
411+
const marker = await _marker
412+
if (marker) {
413+
// @ts-expect-error broken type
414+
marker.setMap(null)
415+
}
416+
}))
403417
mapMarkers.value.clear()
404418
map.value?.unbindAll()
405419
map.value = undefined

0 commit comments

Comments
 (0)