Vue3中AdvancedMarkerView存组件实例不显示,存常量/全局正常的问题
在使用Google Maps的AdvancedMarkerView组件时遇到异常:标记无法显示在地图上。该问题仅在将googleMap实例存储到Vue组件实例(即this.googleMap)时出现,若将实例存为局部常量或挂载到window对象上则可正常显示。需求是将googleMap存在组件实例中,方便后续添加/移除标记,想知道是遗漏了配置还是AdvancedMarkerView的Beta版本导致的问题?
相关代码:
mounted() { const loader = new Loader({ apiKey: 'key', version: 'beta', libraries: ['marker'], }); loader.load().then((google) => { this.googleMap = new google.maps.Map(this.$refs.map, this.mapOptions); // const googleMap = new google.maps.Map(this.$refs.map, this.mapOptions); // window.googleMap = new google.maps.Map(this.$refs.map, this.mapOptions); // 普通Marker可正常显示 new google.maps.Marker({ map: this.googleMap, position: this.home.position, }) // 仅当使用window.googleMap或局部常量googleMap时才正常工作 new google.maps.marker.AdvancedMarkerView({ map: this.googleMap, position: this.home.position, content: this.buildContent(this.home), title: this.home.title }); }); },
核心原因是Vue的响应式系统对Google Maps实例进行了代理包装,而Beta版的AdvancedMarkerView对这种被代理的对象兼容性较差,普通Marker则没有这个问题。以下是可行的解决方式:
不在Vue的
data中声明googleMap:
如果组件data里定义了googleMap: null,Vue会自动对这个属性做响应式处理,劫持其内部属性导致AdvancedMarkerView无法识别。直接删除data中的该声明,在mounted里直接赋值this.googleMap = new google.maps.Map(...)即可,Vue不会对未在data中声明的实例属性做响应式代理。强制关闭响应式代理(针对Vue3):
如果必须在data中声明,使用Vue3提供的markRaw方法包裹地图实例,阻止Vue对其进行响应式处理:import { markRaw } from 'vue' // ... this.googleMap = markRaw(new google.maps.Map(this.$refs.map, this.mapOptions));Vue2的替代方案:
可以将地图实例存储到组件的$options对象中(不会被响应式系统处理),或者用Object.defineProperty添加非枚举属性:// 方式1:存在$options中 this.$options.googleMap = new google.maps.Map(this.$refs.map, this.mapOptions); // 使用时:this.$options.googleMap // 方式2:添加非枚举属性 Object.defineProperty(this, 'googleMap', { value: new google.maps.Map(this.$refs.map, this.mapOptions), writable: true, enumerable: false, configurable: true });升级Beta版本:
虽然主要问题是响应式代理,但也可以尝试升级到最新的Google Maps JavaScript API Beta版本,看看官方是否修复了这类兼容性问题。
内容的提问来源于stack exchange,提问作者Thijs

