Vue.js中使用Google动态导入库遇“google未定义”错误求助
解决Vue中使用Google Maps全局变量时的"google is not defined"错误
问题场景
在index.html中嵌入Google Maps动态导入脚本,随后在Vue组件的created钩子中调用地图初始化方法,代码如下:
index.html中的脚本:
<script> (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({ key: "YOUR_API_KEY", v: "weekly", }); </script>
Vue组件代码:
export default { name: 'GoogleMapsImplementation', async created() { await this.initMap(); }, methods: { async initMap() { const { Map } = await google.maps.importLibrary('maps'); this.map = new Map(document.getElementById('map'), { center: { lat: -34.397, lng: 150.644 }, zoom: 8, }); }, }, };
运行后出现错误:ReferenceError: google is not defined,疑问是否Vue无法使用index.html中定义的全局变量。
问题原因
不是Vue不能使用全局变量,而是Google Maps脚本的异步加载特性导致的:Vue组件的created钩子执行时,index.html中的Google Maps脚本可能还未完成加载,google对象尚未挂载到window全局对象上。
解决方案
1. 等待全局google对象可用后执行代码
在组件的created钩子中添加等待逻辑,确保google存在后再调用初始化方法:
async created() { // 轮询检查google对象是否加载完成 await new Promise(resolve => { const checkGoogleAvailability = () => { if (window.google) { resolve(); } else { setTimeout(checkGoogleAvailability, 100); } }; checkGoogleAvailability(); }); await this.initMap(); }
2. 利用Google Maps的回调机制触发初始化
修改index.html中的脚本,将回调设置为自定义全局函数,待Google Maps加载完成后再执行组件内的地图初始化:
修改index.html中的脚本:
<script> (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);// 将callback改为自定义全局函数 e.set("callback", "initGoogleMaps");a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({ key: "YOUR_API_KEY", v: "weekly", }); </script>
更新Vue组件代码:
export default { name: 'GoogleMapsImplementation', mounted() { // 注册全局回调函数 window.initGoogleMaps = () => { this.initMap(); }; }, methods: { async initMap() { const { Map } = await google.maps.importLibrary('maps'); this.map = new Map(document.getElementById('map'), { center: { lat: -34.397, lng: 150.644 }, zoom: 8, }); }, }, };
3. 声明全局变量避免ESLint报错(可选)
如果项目使用ESLint提示google未定义,可在组件顶部添加全局声明:
/* global google */
或者在项目根目录的.eslintrc.js中配置:
module.exports = { globals: { google: 'readonly' } }
总结
Vue完全支持使用index.html中定义的全局变量,问题核心是异步加载的时序问题。只要确保google对象已挂载到全局后再执行相关代码,即可解决该报错。
内容的提问来源于stack exchange,提问作者Pi L
相关产品推荐
相关产品推荐

