Vue3 Google Maps 标记无法移除

Posted

技术标签:

【中文标题】Vue3 Google Maps 标记无法移除【英文标题】:Vue3 Google Maps marker cannot be removed 【发布时间】:2021-12-26 08:50:59 【问题描述】:

我有一个大部分功能的自制系统,用于在 Vue3 中处理谷歌地图。我没有使用库,因为没有一个库具有我想要的功能(最终),而且我自己实现似乎相对简单(直到本期为止)。

Map组件如下:

<template>
    <div class="map-container">
        <div class="google-map" ref="map"></div>
        <div>
            <slot></slot>
        </div>
    </div>
</template>

<script>
import  Loader  from '@googlemaps/js-api-loader';

export default 
    props:  
        latitude: 
            type: [String, Number],
            default: 0
        , 
        longitude: 
            type: [String, Number],
            default: 0
        ,
        zoom: 
            type: Number,
            default: 15
        ,
    ,
    data()
        return 
            map: null,
            api: null,
            move: null,
        
    ,
    provide: function () 
        return 
            getMap: this.getMap
        
    ,
    watch: 
        latitude() this.updateCenter() ,
        longitude() this.updateCenter() 
    ,
    methods: 
        getMap(callback)
            var self = this;
            function checkForMap() 
              if (self.map) 
                callback(self.map, self.api);
               else 
                setTimeout(checkForMap, 50);
              
            
            checkForMap();
        ,
        updateCenter()
            let center = new this.api.LatLng(this.latitude, this.longitude);
            this.map.panTo(center);
        
    ,  
    mounted()
        let self = this
        let apiKey = document.getElementById('GOOGLE_MAPS_KEY').value
        let loader = new Loader(
            apiKey:  apiKey,
            version: "weekly",
            libraries: ["geometry"]
        );
        loader.load()
            .then((google) => 
                self.api = google.maps;
                self.map = new google.maps.Map(self.$refs.map, 
                    center: 
                        lat: parseFloat(self.latitude), 
                        lng: parseFloat(self.longitude)
                    ,
                    zoom: self.zoom,
                    disableDefaultUI: true,
                );

                // Configure the click listener.
                self.map.addListener("click", (mapsMouseEvent) => 
                    self.$emit('click', mapsMouseEvent)
                );

                // Configure the move listener.
                self.map.addListener("bounds_changed", () =>    
                    if(self.move) clearTimeout(self.move);
                    self.move = setTimeout(() => 
                        let bounds = self.map.getBounds(true);
                        let center = self.map.getCenter();
                        let radius = 100000;

                        if(bounds && center)
                            let northEast = bounds.getNorthEast();
                            radius = self.api.geometry.spherical.computeDistanceBetween(center, northEast);
                        

                        self.$emit('move', 
                            bounds: bounds,
                            radius: Math.round(radius),
                            center: 
                                latitude: center.lat(),
                                longitude: center.lng()
                            
                        )
                    , 800); 
                );
              
            )
            .catch(e => );
  
        

</script>

而标记组件如下:

<template>
    <div></div>
</template>

<script>
export default 
    props: 
        latitude: String, 
        longitude: String, 
        icon: 
            type: String,
            default: '/images/pin.png'
        
    ,
    data()
        return 
            map: null,
            api: null,
            marker: null
        
    ,
    inject: ["getMap"],
    watch: 
        latitude() this.updatePosition() ,
        longitude() this.updatePosition() 
    ,
    mounted()
        let self = this
        this.getMap(function(map, api)
            self.map = map;
            self.api = api;

            self.marker = new api.Marker(
                position: new api.LatLng(self.latitude, self.longitude),
                map: map,
                icon: self.icon,
            );

            self.marker.addListener("click", () => 
                self.$emit('click', self.marker)
            );
        )
        
    ,
    beforeUnmount()
        this.marker.setMap(null);
        this.marker = null;
    ,
    methods: 
        updatePosition()
            this.marker.setPosition( new this.api.LatLng( parseFloat(this.latitude), parseFloat(this.longitude) ) );
        
    

</script>

然后我有一个组件,它使用这些组件来显示带有标记的地图。

<template>    
    <div>
        <div class="admin-site-map">
            <google-map :center="center" :zoom="15">
                <map-marker v-for="site in sites" :key="site.id" 
                    :latitude="site.latitude" 
                    :longitude="site.longitude" 
                    @click="markerClicked"
                />
            </google-map>        
        </div>
    </div>
</template>

<script>
import GoogleMap from '@/components/Core/Maps/GoogleMap';
import Marker from '@/components/Core/Maps/Marker';
export default 
    components:  GoogleMap, mapMarker: Marker ,  
    props: ['sites'],
    data()
        return 
            center: lat: 0, lng: 0,
        
    ,
    methods: 
        markerClicked(value)
            console.log('click: ', value)
          
    

</script>

当标记(站点)列表发生变化时,我可以看到在已删除的标记上调用了beforeUnmount 方法,但标记并没有从地图上消失,我什至仍然可以单击标记并接收事件中发出的null 值。 奇怪的是,调用 this.marker.setVisible(false) 确实有效,并隐藏了标记。 我已经坚持了一段时间,所以任何见解或帮助将不胜感激。谢谢!

【问题讨论】:

我无法复制this(稍作修改的版本)。我建议您尝试逐段删除代码(不相关的方法,观察者,...),直到它起作用为止。 【参考方案1】:

感谢User28,我终于找到了解决方案: 在标记组件上,marker(Google 标记对象保存到的位置)不应是反应性属性。将数据方法更改为

return 
    map: null,
    api: null

修复了问题(即删除marker)。

【讨论】:

以上是关于Vue3 Google Maps 标记无法移除的主要内容,如果未能解决你的问题,请参考以下文章

从 Google Maps JS API 中移除其他地方?

google_maps_flutter - 自定义标记图标:无法启用 MyLocation 图层,因为未授予位置权限

google-maps kml,如何标记线串?

如何在 react-google-maps 中添加标记?

标记未显示在 Google Maps API 中

当用户点击 react-google-maps 中的地图或标记时执行操作