Integrating Google Maps in vue.js

I was searching for a different issue and found this one, there is another way that you could achieve this without having to add it in index.html.

I faced a similar problem where I had to use two Google API keys for different environments so hard-coding it in to index.html was not a good idea, I did this if it helps anyone -

main.js

export const loadedGoogleMapsAPI = new Promise( (resolve,reject) => {

      window['GoogleMapsInit'] = resolve;

      let GMap = document.createElement('script');

      GMap.setAttribute('src',
     `https://maps.googleapis.com/maps/api/js?key=${process.env.GOOGLE_API_KEY}&callback=GoogleMapsInit&region=IN`);

      document.body.appendChild(GMap); 
});

MapElem.vue

<template>
   <div id="map"></div>
</template>

<script>
   import {loadedGoogleMapsAPI} from '@/main'

   export default {
     name: 'MapEl',
     mounted(){  
       loadedGoogleMapsAPI.then(()=>{
         this.initMap()
       });
     },
    methods:{
     initMap(){
        console.log(google.maps); //You can now access google maps object here
        new google.maps.Map(document.getElementById('map'), {
          // You configuration goes here
        })
     }
    }
</script>

It's pretty straightforward, you write a Promise in main.js which will resolve to the callback initiated by Google script ( which we dynamically appended to the body ). Once the Promise is resolved you can access the map object in your component.


I'd suggest using npm google-maps instead of adding a script in index.html. You might not need to call google-maps API in every pages, and I'd say it's better to use Webpack properly. You can use npm install google-maps

import GoogleMapsLoader from 'google-maps'

mounted: function () {
  GoogleMapsLoader.load(function(google) {
    let map = new google.maps.Map(document.getElementById('map'), {
      zoom: 15,
      center: position
    })
  })
}

It's a little fussy to get this working without using a library, and there are probably cleaner ways, but you can simply import the library and use it in your components if you want to get up and running.

First, don't use the defer & async options in the <script> tag. Load it in the index.html:

<script src="https://maps.googleapis.com/maps/api/js?key=yourKey"></script>

Then in your component you can access the global google and pass it an element once the component is setup. For example using the setup from the Vuejs cli:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>

    <div id="myMap"></div>
  </div>
</template>

<script>
export default {
  name: 'hello',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }},
  mounted: function() {
        console.log("map: ", google.maps)
            this.map = new google.maps.Map(document.getElementById('myMap'), {
            center: {lat:61.180059, lng: -149.822075},
            scrollwheel: false,
            zoom: 4
            })
  }

}
</script>
<style scoped>
    #myMap {
    height:300px;
    width: 100%;
   }
</style>

There's a different way if you would like to keep the code contained in a Component using the async loader $Scriptjs.

Install via npm

npm install scriptjs

import into your component

import $Scriptjs from 'scriptjs

load the script in the mounted hook (assuming you have a method in your component called initMap)

...
mounted () {
  $Scriptjs('https://maps.googleapis.com/maps/api/js?key={YOUR_KEY}', () => {
      this.initMap()
}
...