高德地图marker使用vue组件

198 阅读2分钟

简介

高德地图JSAPI的marker是大家常用的一个组件,由于该组件通过dom实现地图标号,可以方便使用CSS等其他html里常见的技术而被大量使用,下面主要介绍在vue中怎么将vue的组件与marker结合起来。

低配版方法

在vue2版本时,我们使用marker只有一个相对方便的方式就是通过ref获取div元素再通过监听组件的updated生命周期同步更新marker的content,从而实现以vue组件与marker的结合。代码示例如下:

<template>
  <div style="height:500px;" id="mapContainer"></div>
  <div style="display: none;">
    <div ref="markerRef">
      <el-image :src="xxxx"></el-image>
    </div>
  </div>
</template>
<script>
export default {
  mounted(){
    const center = [120, 31]
    const map = new AMap.Map('mapContainer', {
      center
    })
    const marker = new AMap.Marker({
      position: center,
      content: this.$refs.markerRef
    })
    map.add(marker)
    this.marker = marker
  },
  updated(){
    if(this.marker){
      this.marker.setContent(this.$refs.markerRef)
    }
  }
}
</script>

在这个代码示例中,我们通过一个隐藏的div来渲染marker需要的数据,并在mounted生命周期中通过ref拿到渲染的div的dom并赋值给marker的content,在updated生命周期中更新marker的content。当我们使用的vue组件仅用于渲染展示时,该操作没有什么问题,但一旦涉及到v-model之类的交互时,会直接无法使用,因为vue的组件已经被破坏,下面我们看看在vue3中怎么实现一个高配的marker。

vue3的高配方法

在vue3中新增加了Teleport组件,该组件支持将vue渲染的结果直接传送到指定的dom元素中,而不破坏vue的所有交互,通过这一特性,我们可以给marker创建一个空白的div,并将组件直接传送过去,下面我们看一个示例: 示例中我们看到在生成marker时我们只生成了一个marker-uuid的空白div,并在将marker添加到地图后,将uuid等数据存放到一个响应式的markers数组中,在template中我们对数组进行循环,并使用Teleport组件将el-image的渲染结果传送到了marker的div中,这样可以保证我们既使用了地图组件,又能使用vue中大量的组件。

结束语

上述主要是在marker中使用vue组件,这个场景其实比较少见,更多的时候我们会在InfoWindow中使用各种组件,比如表格、图表、表单等等,通过Teleport,我们可以方便的将地图与vue结合起来,下面我们看下InfoWindow的示例,InfoWindowMarker的主要区别在于,当InfoWindow没有执行open方法前是不会创建需要的dom,所以我们必须在执行一次open之后在进行divId的赋值,从而保证Teleport可以正确的将渲染结果传送到指定的div中。

最后,如果大家有需要,可以直接使用vue的组件库: @vuemap/vue-amap