这篇文章主要为大家展示了“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: { 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如何开发高德地图应用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!