Introduce
Lately I have to work a bit with google map but in vue. And if you learn about google map, you also know to integrate google map into your website, you will have to insert a google script link, but if you work with SPA (here I say Laravel + Vue) then you also know there will be only one main blade page from which to render the Vue pages. You can also quickly insert the page, but obviously that’s not a good way. After that, I had to learn more and found out how to use google map in Vue more useful. Check it out below.
Well this article will only guide how to integrate google map into vue without showing how to configure google map from console. That means this article will go from the fact that you already have an api key of google map already.
vue2-google-maps Plugin
If you search google with the keyword ” using google map in vuejs
” then you will surely see the plugin name in the first results.
Choosing this way has an advantage of being fast and convenient. You just need to run the install command and with a few lines of basic code is integrated, ready to use.
And according to its documentation, the first thing I have to do is use the command to install it into my project
npm install vue2-google-maps
Next, you will create a js file to declare to the vue that I will use this plugin, there are two directions, if you want to go anywhere you can call the vue component and do not have to declare again. then you will declare immediately in the js file used to render vue into the laravel blade. Kind of, it’s the js file with this code
1 2 3 4 5 6 7 8 | const app = new Vue({ el: '#app', router, store, i18n, components: {App} }); |
Then also if you do not have the need to use map in many places but in just a few pages, it is recommended to split it into a separate js file in the directory where the shared ones can be called back (usually utils
). . utils/gmaps.js
just name it utils/gmaps.js
. And on the page you want to use you just call
1 2 | import 'utils/gmaps.js'; |
is done. Note that the path you call to this utils directory must be correct.
The content of the declaration will be as follows.
1 2 3 4 5 6 7 8 9 10 | import Vue from 'vue' import * as VueGoogleMaps from 'vue2-google-maps' Vue.use(VueGoogleMaps, { load: { key: 'YOUR_API_TOKEN', }, installComponents: true }) |
And the setup is just like that, From here you can instantiate your map using the component in the vue template.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <GmapMap :center="{lat:10, lng:10}" :zoom="7" map-type-id="terrain" style="width: 500px; height: 300px" > <GmapMarker :key="index" v-for="(m, index) in markers" :position="m.position" :clickable="true" :draggable="true" @click="center=m.position" /> </GmapMap> |
However, besides the advantage of being quick, this method has a bit of a downside. In the process of using it, at first I thought it was okay to do so, but my demand started to get bigger. I need to use some additional google services for example. In the doc, the description is as simple as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <template> <GmapMarker ref="myMarker" :position="google && new google.maps.LatLng(1.38, 103.8)" /> </template> <script> import {gmapApi} from 'vue2-google-maps' export default { computed: { google: gmapApi } } </script> |
However, I did it and I still struggled and was told that the value of google is null / undefine because js is asynchronous, but the google guy has not loaded, the place I need to use has already run. , and after a hard time searching and searching, there is a temporary way to fix that is to use the call this.$gmapApiPromiseLazy().then(//... your code here)
to make sure your google guy you have finished loading. ( https://github.com/xkjyeah/vue-google-maps/wiki/vue-google-maps-FAQ#where-is-my-google )
This is a bit of a nuisance that I feel, and besides, surely this guy has the disadvantages of a plugin as required when you use it larger than what this plugin offers. Obviously if you need something that google service has provided but this plugin has not yet developed, you will have to wait until this developer develops to the part you need, but do not know how to wait. until ever.
Fortunately for me, after a long time searching on google, I have found a pretty good way to use map in vue. I would like to share again below.
Loading Google Maps API
References: https://markus.oberlehner.net/blog/using-the-google-maps-api-with-vue/
As far as I understand, this integration will basically rely on you creating script element and appending to the page header. You may wonder what I said at the beginning is what it means to put the script into the blade or now want to put it in. The other thing that I put in is that all the pages I will load and for this one I will write a function in my own js file. Where I need it, I declare it to append to it.
Let’s try it out together.
I will also create an utils
folder with gmaps file similar to the above method with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <span class="token keyword">const</span> <span class="token constant">API_KEY</span> <span class="token operator">=</span> <span class="token string">'YOUR_API_KEY'</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">CALLBACK_NAME</span> <span class="token operator">=</span> <span class="token string">'gmapsCallback'</span> <span class="token punctuation">;</span> <span class="token keyword">let</span> initialized <span class="token operator">=</span> <span class="token operator">!</span> <span class="token operator">!</span> window <span class="token punctuation">.</span> google <span class="token punctuation">;</span> <span class="token keyword">let</span> resolveInitPromise <span class="token punctuation">;</span> <span class="token keyword">let</span> rejectInitPromise <span class="token punctuation">;</span> <span class="token comment">/** * Promise xử lý quá trình khởi tạo * trạng thái của google maps script. */</span> <span class="token keyword">const</span> initPromise <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">resolve <span class="token punctuation">,</span> reject</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> resolveInitPromise <span class="token operator">=</span> resolve <span class="token punctuation">;</span> rejectInitPromise <span class="token operator">=</span> reject <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">init</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">/** * Nếu Google Maps đã được khởi tạo trước đó * return promise */</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> initialized <span class="token punctuation">)</span> <span class="token keyword">return</span> initPromise <span class="token punctuation">;</span> initialized <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> <span class="token comment">/** * Hàm call back được gọi khi google được load thành công * Ở đây nó sẽ thực hiện resolve ra biến window.google chính là google object * được dùng để khởi tạo google map, google service như trong document của google. */</span> window <span class="token punctuation">[</span> <span class="token constant">CALLBACK_NAME</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">resolveInitPromise</span> <span class="token punctuation">(</span> window <span class="token punctuation">.</span> google <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">/** * Tạo một element là script với src là đường dẫn để gọi google map * và chèn nó vào head của page * nếu có lỗi xảy ra sẽ reject promise để khi gọi để những chỗ gọi đến nó có thể catch được. */</span> <span class="token keyword">const</span> script <span class="token operator">=</span> document <span class="token punctuation">.</span> <span class="token function">createElement</span> <span class="token punctuation">(</span> <span class="token string">'script'</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> script <span class="token punctuation">.</span> async <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> script <span class="token punctuation">.</span> defer <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">;</span> script <span class="token punctuation">.</span> src <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">https://maps.googleapis.com/maps/api/js?key=</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token constant">API_KEY</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token string">&callback=</span> <span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> <span class="token constant">CALLBACK_NAME</span> <span class="token interpolation-punctuation punctuation">}</span></span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">;</span> script <span class="token punctuation">.</span> onerror <span class="token operator">=</span> rejectInitPromise <span class="token punctuation">;</span> document <span class="token punctuation">.</span> <span class="token function">querySelector</span> <span class="token punctuation">(</span> <span class="token string">'head'</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">appendChild</span> <span class="token punctuation">(</span> script <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token comment">// return promise để chỗ gọi biết được rằng đã được xử lý xong.</span> <span class="token keyword">return</span> initPromise <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
After reading the above comments and code, you will understand all or part of the idea of using google map in vue.
So now with the need to use google map, I just need to await
this init function to get the google object object and use it.
Try it out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | <template> <div class="App"/> </template> <script> import gmapsInit from './utils/gmaps'; export default { name: 'App', async mounted() { try { const google = await gmapsInit(); const geocoder = new google.maps.Geocoder(); const map = new google.maps.Map(this.$el); geocoder.geocode({ address: 'VietNam' }, (results, status) => { if (status !== 'OK' || !results[0]) { throw new Error(status); } map.setCenter(results[0].geometry.location); map.fitBounds(results[0].geometry.viewport); }); } catch (error) { console.error(error); } }, }; </script> <style> html, body { margin: 0; padding: 0; } .App { width: 100vw; height: 100vh; } </style> |
The code above shows an example of using Geocoder
to convert an address from a string to a coordinate form and thereby create a basic map.
Then now with the creation of the google object: google object, you can use google map in vue like in the google documentation already. You can freely do without fear of being restricted anymore, just google will grant: p.
Good luck!