简介
高德地图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
的示例,InfoWindow
与Marker
的主要区别在于,当InfoWindow
没有执行open方法前是不会创建需要的dom,所以我们必须在执行一次open之后在进行divId的赋值,从而保证Teleport
可以正确的将渲染结果传送到指定的div中。
最后,如果大家有需要,可以直接使用vue的组件库: @vuemap/vue-amap