高德地图中使用 Vue 组件自定义Marker标点或InfoWindow信息窗体

原理

在高德地图中使用Vue组件进行自定义Marker、InfoWindow

new AMap.Marker(opts: MarkerOptions)

new AMap.InfoWindow(opts: InfoOptions)

属性 描述
opts.content 类型:`(string HTMLElement)`

查看文档可以知道 content 的属性可以接收HTMLElement元素,我们可以通过创建一个HTMLElement元素,然后将vue组件挂载到这个元素上。

代码示例

  • vue3
  • ts
  • amap-jsapi-loader

CreateHTML.ts 创建元素

使用createApp创建vue实例,传入组件

返回元素、vue实例(这个实例返回很重要)

ts 复制代码
/**
 * 创建vue元素
 */
export const createHTML = (comp: Component, props?: Record<string, unknown>) => {
  const element = document.createElement('div')
  const app = createApp(comp, props)
  app.mount(element)

  return {
    element, app
  }
}

vue组件

vue 复制代码
<script setup lang="ts">
defineOptions({
  name: 'Marker'
})
const props = defineProps<{
  name: string
}>()
</script>

<template>
  <h2>{{ props.name }}</h2>
</template>

<style scoped>
h2 {
  background: #115c5c;
  padding: 5px 10px;
  border-radius: 5px;
}
</style>

创建自定义Marker

拿Marker做个示例 InfoWindow同理

ts 复制代码
// 创建vue元素
const {app,element} = createHTML(MyComp,{
    name: '这是一个自定义的Marker',
})

// 创建覆盖物
const marker = new AMap.Marker({
    content: element,
    // ...otherConf
})

// 添加到地图
map.add(marker)

这样就创建了一个自定义Marker。我们也可以在vue调试工具中看到这个App实例。

这样本来是没什么问题的,但是......

当我们将marker销毁的时候App实例仍然存在,所以当我们对marker(InfoWindow)进行移除的同时,需要把App的实例也进行销毁。

ts 复制代码
// 移除标点
marker.remove()
// 销毁app
app.unmount()

扩展

使用pinia 或者组件库

由于我们是创建了一个新的vue实例,如果我们要在组件内使用pinia、或者其他组件库、插件,我们需要再写一遍配置

修改创建HTML方法

ts 复制代码
/**
 * 创建vue元素
 */
export const createHTML = (comp: Component, props?: Record<string, unknown>) => {
  const element = document.createElement('div')
  const app = createApp(comp, props)

  /** 引入pinia 或者其他配置**/
  
  // 引入相同的pinia 可以与其他实例通过pinia进行通信
  app.use(pinia)
  
  /** 引入pinia **/
  

  app.mount(element)

  return {
    element, app
  }
}

新的问题

问题1

由于组件动态生成,生成后异步获取数据,元素依旧可能变化,最后生成的元素高度、宽度可能不定,导致Marker、InfoWindow生成的位置不正确。

不完全解决办法

  1. 固定元素宽高
  2. 不在组件内异步获取数据,在组件外获取数据后再传入组件,生成Marker
相关推荐
嚴寒10 分钟前
Mac 安装 Dart & Flutter 完整开发环境指南
前端·macos
用户66006766853914 分钟前
从变量提升到调用栈:V8 引擎如何 “读懂” JS 代码
前端·javascript
白兰地空瓶14 分钟前
【深度揭秘】JS 那些看似简单方法的底层黑魔法
前端·javascript
进阶的小叮当18 分钟前
Vue代码打包成apk?Cordova帮你解决!
android·前端·javascript
天天进步201521 分钟前
从零开始构建现代化React应用:最佳实践与性能优化
前端·react.js·性能优化
程序媛_MISS_zhang_011028 分钟前
浏览器开发者工具(尤其是 Vue Devtools 扩展)和 Vuex 的的订阅模式冲突
前端·javascript·vue.js
fruge30 分钟前
Vue3.4 Effect 作用域 API 与 React Server Components 实战解析
前端·vue.js·react.js
神秘的猪头42 分钟前
🌐 CSS 选择器详解:从基础到实战
前端·javascript
远山枫谷44 分钟前
CSS选择器优先级计算你真的会吗?
前端·css
Forever_xl44 分钟前
埋点监控平台全景调研
前端