Vue3 Vite项目中如何通过第三方组件访问google.maps命名空间
问题:Vue3+TypeScript项目中访问第三方组件懒加载的Google Maps命名空间
我有一个采用Vue3+TypeScript、基于Vite和Yarn构建的项目,使用名为vue3-google-map的Google Maps依赖包。目前在Map组件中Google Maps可正常运行:
<template> <GoogleMap id="map" ref="mapRef" :api-key="Backbone.mapSettings.key" :center="Backbone.mapSettings.center" :zoom="Backbone.mapSettings.zoom" style="width: 100%; height: 100%" /> </template> <script setup lang="ts"> import { onMounted } from 'vue'; import { ref, watch } from 'vue'; import { GoogleMap } from 'vue3-google-map'; let gmap: google.maps.Map | null = null; let mapRef = ref<google.maps.Map | null>(null); onMounted(() => { initMap(); }); function initMap() { watch(() => (mapRef.value as any)?.ready as any, (x) => { gmap = (mapRef.value as any).map; }); } </script>
但在另一个TypeScript文件中访问google.maps命名空间定义变量时,浏览器编译报错:
export default class MapSettings { public center: google.maps.LatLng = new google.maps.LatLng(56.26392, 9.501785); }
错误信息:
MapSettings.ts:6 Uncaught ReferenceError: google is not defined
at <instance_members_initializer> (MapSettings.ts:6:38)
at new MapSettings (MapSettings.ts:3:1)
推测google.maps是<GoogleMap>组件初始化后懒加载的,尝试以下方法均未解决:
- 安装
@types/google.maps无效 - 直接在index.html引入Google Maps脚本会触发控制台警告:
Google Maps already loaded outside @googlemaps/js-api-loader.This may result in undesirable behavior as options and script parameters may not match. - 换用
vue3-google-maps库问题依然存在
解决方案
1. 利用组件加载完成事件延迟初始化MapSettings
由于google.maps是组件懒加载的,不能在类属性初始化阶段直接使用,需将初始化逻辑改为异步,等待地图加载完成后执行:
步骤1:在Map组件中暴露加载完成的Promise
修改Map组件的script setup,创建一个Promise用于通知外部Google Maps已加载:
import { onMounted, ref, watch } from 'vue'; import { GoogleMap } from 'vue3-google-map'; let mapRef = ref<any>(null); // 暴露Promise,外部可监听Google Maps加载完成事件 export const googleMapsLoaded = new Promise<typeof google.maps>((resolve) => { watch(() => mapRef.value?.ready, (isReady) => { if (isReady) { resolve(window.google.maps); } }); }); onMounted(() => { initMap(); }); function initMap() { // 原有逻辑保持不变 }
步骤2:修改MapSettings类,异步初始化属性
import { googleMapsLoaded } from './MapComponent.vue'; // 替换为你的Map组件路径 export default class MapSettings { public center: google.maps.LatLng | null = null; constructor() { // 等待Google Maps加载完成后初始化center googleMapsLoaded.then((maps) => { this.center = new maps.LatLng(56.26392, 9.501785); }); } }
2. 补充全局类型声明,消除TS编译报错
安装@types/google.maps后,在项目的env.d.ts中添加全局声明,确保TypeScript能识别window.google的类型:
// env.d.ts declare global { interface Window { google: typeof google; } } export {};
3. 手动控制Google Maps加载,避免重复加载警告
通过@googlemaps/js-api-loader手动加载Google Maps,替代组件自动加载逻辑,既解决命名空间访问问题,又消除重复加载警告:
步骤1:安装加载器
yarn add @googlemaps/js-api-loader
步骤2:创建加载模块
// google-maps-loader.ts import { Loader } from '@googlemaps/js-api-loader'; const loader = new Loader({ apiKey: '你的Google Maps API密钥', // 可从项目配置中读取 version: 'weekly', // 其他配置需与组件原配置保持一致 }); export const loadGoogleMaps = async () => { await loader.load(); return window.google.maps; };
步骤3:修改Map组件,移除自动加载配置
<template> <GoogleMap id="map" ref="mapRef" :center="Backbone.mapSettings.center" :zoom="Backbone.mapSettings.zoom" style="width: 100%; height: 100%" /> </template> <script setup lang="ts"> import { onMounted, ref } from 'vue'; import { GoogleMap } from 'vue3-google-map'; import { loadGoogleMaps } from './google-maps-loader'; let mapRef = ref<any>(null); let gmap: google.maps.Map | null = null; onMounted(async () => { // 手动加载Google Maps后再初始化地图逻辑 await loadGoogleMaps(); gmap = mapRef.value?.map; }); </script>
步骤4:修改MapSettings类,异步初始化
import { loadGoogleMaps } from './google-maps-loader'; export default class MapSettings { public center: google.maps.LatLng | null = null; constructor() { this.init(); } private async init() { const maps = await loadGoogleMaps(); this.center = new maps.LatLng(56.26392, 9.501785); } }
内容的提问来源于stack exchange,提问作者Farsen
相关产品推荐
相关产品推荐

