您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Vue如何開發高德地圖應用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Vue如何開發高德地圖應用”這篇文章吧。
因為使用 js sdk 應用,腳本文件本身體積很大,所以要注意下加載的白屏時間,解決用戶體驗問題,目前絕大部分產品應用都是 SPA 單頁面應用系統,所以我封裝一個異步加載的方法:
const loadScripts = async scripts => { const get = src => { return new Promise(function(resolve, reject) { const el = document.createElement('script') el.addEventListener('load', function() { resolve(src) }, false) el.addEventListener('error', function() { reject(src) }, false) el.id = src.id el.src = src.url document.getElementsByTagName('body')[0].appendChild(el) || document.getElementsByTagName('head')[0].appendChild(el) }) } const myPromises = scripts.map(async script => { if (document.getElementById(script.id) === null) { return await get(script) } }) return await Promise.all(myPromises) } export default loadScripts
這個方法在加載腳本的時候先去判斷頁面是否存在該腳本,如果存在就不會加載第二次,然后再利用加載完畢回調執行相關方法。
如果系統中有多個頁面需要地圖應用業務,那么需要封裝一個通用型的地圖組件,提高項目可維護性,我這邊就簡單的封裝下地圖應用:
<template> <div :style="{ width: width, height: height }" class="amap-container" > <div ref="amap" class="amap"> <slot /> </div> </div> </template> <style lang="scss" scoped> .amap-container { .amap { width: 100%; height: 100%; } } </style>
指定一個地圖應用容器,外面包裹一層指定高寬,高寬作為外部變量傳入,業務邏輯如下:
import loadScripts from '@/loadScripts' export default { name: 'AMapContainer', props: { width: { require: false, type: String, default: '100%' }, height: { require: false, type: String, default: '600px' }, options: { require: false, type: Object, default: () => {} } }, data: () => ({ amap: null, amapInfo: { key: 'xxxxxxxxxxxxxx' } }), created() { this.initAMap() }, beforeDestroy() { // 銷毀地圖 if (!this.amap) { return } this.amap.destroy() this.amap = null }, methods: { initAMap() { loadScripts([{ id: 'ampa', url: `https://webapi.amap.com/maps?v=2.0&key=${this.amapInfo.key}&plugin=AMap.PolygonEditor` }]).then(() => { this.amap = new window.AMap.Map(this.$refs['amap'], this.options) this.$emit('map', this.amap, window.AMap) }) } } }
應用加載的時候初始化地圖容器:異步加載高德地圖 js sdk 然后回調方法里進行實例化地圖應用,并且把地圖實例化的對象傳入 $emit 事件里,方便父類組件需要。另外注意要在銷毀生命周期里對地圖應用進行銷毀,否則會占用大量的系統內存。
封裝好組件后就可以在對應的頁面進行引入組件使用即可:
<template> <amap-container height="100%" :options="amapOptions" @map="getAMapData" /> </template> <script> import AMap from '@/components/AMap' export default { name: 'AMapDemo', components: { 'amap-container': AMap }, data: () => ({ amapOptions: { zoom: 14, resizeEnable: true, viewMode: '3D', mapStyle: 'amap://styles/normal' }, AMap: null, // 地圖對象 amap: null // 當前地圖實例 }), methods: { /** * 地圖加載完畢回調 * @param amap * @param AMap */ getAMapData(amap, AMap) { // 從組件獲取地圖 amap 對象 this.amap = amap // 從組件獲取地圖 AMap 靜態對象 this.AMap = AMap } } } </script>
然后在上面基礎上展開相關業務。對于地圖應用來說,最核心的數據就是地圖應用中的坐標,無論是地圖的標記元素,折線元素(軌跡等),繪制圖元素等,只需要獲取對應的經緯度數據存到數據庫即可,至于怎么獲取這邊不再詳述。
之前制作的地圖應用,在標記的詳細界面(選擇某個標記左鍵打開界面),這個界面是需要傳入原生 document 對象,但是在 vue 對象里面不符合這種寫法,所以導致之前很多系統都是花大量的時間去編寫 dom 結構,甚是頭疼,后續為了解決這個問題,vue 是否有相關方法掛載組件獲取真實的 document 對象,查閱相關文檔后,確實有這個 api : Vue.extend,利用這個 api 掛載組件對象即可得到實例化組件的對象。
import ContextCard from './components/ContextCard' // 創建標記 const marker = new this.AMap.Marker({ map: this.amap, position: [119.058904, 33.537069] }) // 綁定點擊事件 marker.on('click', this.markerInfoWindow) // 點擊打開彈窗 const markerInfoWindow = () => { // 引入 Vue 組件構造器實例化 const ContextCardContent = Vue.extend(ContextCard) // 掛載組件 const contextCardContent = new ContextCardContent().$mount() // 實例化窗口對象 this.amapInfoWindow = new this.AMap.InfoWindow({ isCustom: true, content: contextCardContent.$el, offset: new this.AMap.Pixel(0, -40) }) // 打開窗口 this.amapInfoWindow.open(this.amap, marker.getPosition()) // 監聽組件事件關閉窗口 contextCardContent.$on('closeWindow', () => this.amapInfoWindow.close()) }
ContextCard.vue 組件:
<template> <el-card class="context-box-card box-card"> <div slot="header" class="header"> <span>卡片名稱</span> <el-button type="text" class="close-btn" @click="closeWindow">關閉</el-button> </div> <div v-for="o in 4" :key="o" class="text item"> {{ '列表內容 ' + o }} </div> </el-card> </template> <script> export default { name: 'AMapContextCard', methods: { closeWindow() { this.$emit('closeWindow') } } } </script> <style lang="scss" scoped> .context-box-card { width: 320px; height: 200px; .header { display: flex; justify-content: space-between; align-items: center; } ::v-deep .el-card__header { padding: 5px 20px; } } </style>
上面就是一個標點點擊打開標記彈窗的詳細信息,利用 Vue.extend 構造器進行實例化組件。這樣很大程度上提高項目健壯性。
import Vue from "vue"; import App from "./App.vue"; import Element from "element-ui"; import "normalize.css/normalize.css"; import "element-ui/lib/theme-chalk/index.css"; Vue.config.productionTip = false; Vue.use(Element); new Vue({ render: (h) => h(App) }).$mount("#app");
以上是“Vue如何開發高德地圖應用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。