恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
vue-amap 点标记覆盖物 el-amap-marker:从基础用法、自定义内容到响应式原理详解
首页
资讯中心
/
vue-amap 点标记覆盖物 el-amap-marker:从基础用法、自定义内容到响应式原理详解
vue-amap 点标记覆盖物 el-amap-marker:从基础用法、自定义内容到响应式原理详解
发布时间:2026/10/14 15:19:01
前端UI组件GIS【免费下载链接】vue-amap 基于 Vue 2.x 和高德地图的地图组件项目地址https://gitcode.com/gh_mirrors/vu/vue-amap点击查看免费下载本文以 vue-amap 的覆盖物组件el-amap-marker点标记/Marker为主体完整覆盖官方文档中的基础示例、静态/动态属性、ref 帮助方法与事件体系并结合 amap-marker.vue 源码 与 register-component 混入 深入解析其响应式更新链路、自定义内容content / template / vnode / contentRender / 插槽的编译实现。读完本文你可以在 Vue 2 项目中以声明式方式创建、拖拽、批量管理地图点标记并理解每一项属性背后的实现机制。一、组件定位与安装前提el-amap-marker是 vue-amap 对高德AMap.Marker的 Vue 封装必须作为el-amap地图组件的子级使用。组件通过 入口文件 的VueAMap.install统一注册执行Vue.use(VueAMap)后el-amap、el-amap-marker等 13 个组件自动注册为全局组件。使用前需按 README 完成初始化npm install -S vue-amapimport Vue from vue; import VueAMap from vue-amap; Vue.use(VueAMap); VueAMap.initAMapApiLoader({ key: your amap key, plugin: [AMap.Autocomplete, AMap.PlaceSearch, AMap.Scale, AMap.OverView, AMap.ToolBar, AMap.MapType, AMap.PolyEditor, AMap.CircleEditor], // 高德 sdk 版本默认为 1.4.4 v: 1.4.4 });注意若项目同时使用高德原生 SDK建议保持import VueAMap from vue-amap的导入命名避免与全局AMap冲突参见 兼容高德原生 SDK。二、基础示例批量管理点标记以下示例完整继承自 官方点标记文档演示了单个 marker、v-for批量渲染 marker、VNode 渲染 marker 三种形态以及切换可见性、修改位置、切换可拖拽、增删 marker 等动态操作template div classamap-page-container el-amap vidamapDemo :zoomzoom :centercenter classamap-demo el-amap-marker vidcomponent-marker :positioncomponentMarker.position :content-rendercomponentMarker.contentRender /el-amap-marker el-amap-marker v-for(marker, index) in markers :positionmarker.position :eventsmarker.events :visiblemarker.visible :draggablemarker.draggable :vidindex /el-amap-marker /el-amap div classtoolbar button typebutton v-on:clicktoggleVisibletoggle first marker/button button typebutton v-on:clickchangePositionchange position/button button typebutton v-on:clickchnageDragglechange draggle/button button typebutton v-on:clickaddMarkeradd marker/button button typebutton v-on:clickremoveMarkerremove marker/button /div /div /template style .amap-demo { height: 300px; } /style script module.exports { name: amap-page, data() { return { zoom: 14, center: [121.5273285, 31.21515044], markers: [ { position: [121.5273285, 31.21515044], events: { click: () { alert(click marker); }, dragend: (e) { // 拖拽结束后将地图坐标写回 data实现双向同步 this.markers[0].position [e.lnglat.lng, e.lnglat.lat]; } }, visible: true, draggable: false, template: span1/span } ], // contentRender 方式传入 render 函数函数内可用 this 访问组件实例 componentMarker: { position: [121.5273285, 31.21315058], contentRender: (h, instance) h(div, { style: { background: #80cbc4, whiteSpace: nowrap, border: solid #ddd 1px, color: #f00 }, on: { click: () { const position this.componentMarker.position; this.componentMarker.position [position[0] 0.002, position[1] - 0.002]; } } }, [marker inner text]) } }; }, methods: { changePosition() { let position this.markers[0].position; this.markers[0].position [position[0] 0.002, position[1] - 0.002]; }, chnageDraggle() { this.markers[0].draggable !this.markers[0].draggable; }, toggleVisible() { this.markers[0].visible !this.markers[0].visible; }, addMarker() { this.markers.push({ position: [121.5273285 (Math.random() - 0.5) * 0.02, 31.21515044 (Math.random() - 0.5) * 0.02] }); }, removeMarker() { if (!this.markers.length) return; this.markers.splice(this.markers.length - 1, 1); } } }; /script几个关键实践点v-for渲染markers数组增删会直接驱动地图上的 marker 增删addMarker/removeMarker因为每个el-amap-marker是独立 Vue 实例销毁时混入的destroyed钩子会调用setMap(null)将其从地图摘除见 register-component.js#L32-L41。dragend回写坐标拖拽结束后从MapsEvent的e.lnglat读取新坐标并写回 data这是实现地图拖拽 → Vue 状态单向数据流的标准姿势。vid绑定:vidindex会把 marker 实例按该 id 注册进AMapManager见第六节方便在任意位置通过amapManager.getComponent(vid)拿到原生实例。三、静态属性仅初始化配置文档将 marker 的属性分为静态与动态两类。静态属性只在new AMap.Marker(options)初始化时生效不支持响应式名称类型说明vidStringmarker 对象 id用于向AMapManager注册topWhenClickBoolean鼠标点击时 marker 是否置顶默认false不置顶v1.3 新增bubbleBoolean是否将覆盖物的鼠标或 touch 等事件冒泡到地图上默认falsev1.3 新增autoRotationBoolean是否自动旋转。moveAlong动画路径方向变化时点标记是否自动调整角度默认falseIE8 以下不支持旋转该属性无效从源码结构看静态/动态的区分机制在 register-component.js#L111-L137setPropWatchers会为每个 prop 调用getHandlerFun查找对应的setXxx方法找不到 setter 的 prop 只写入初始化 options不再建立 watcher。这也是使用时的核心约束——不要依赖响应式去修改静态属性。四、动态属性支持响应式以下属性支持通过 Vue 响应式系统实时更新每个属性都映射到高德AMap.Marker的对应 setter名称类型说明visibleBoolean点标记是否可见默认truezIndexNumber点标记叠加顺序默认100positionArray点标记在地图上显示的位置默认为地图中心点offsetArray显示位置偏移量默认Pixel(-10, -34)。指定position后默认以 marker 左上角为基准点若需使 marker 指定位置对准position需按 marker 尺寸设置偏移量iconString点标记图标可为本地图标地址存在合法content时此属性无效contentString点标记显示内容可为 HTML 要素字符串或 DOM 对象content有效时覆盖icontemplateString传入 Vue 模板字符串v0.4.0 起支持vnodeVNode 或(Instance) VNodeVNode 渲染v0.4.2 起支持contentRender(createElement, instance) VNodeVNode render 渲染v0.4.3 起支持draggableBoolean是否可拖拽移动默认falseraiseOnDragBoolean拖拽时是否开启 marker 离开地图的效果cursorString鼠标悬停时的鼠标样式须符合 CSS cursor 规范angleNumber旋转角度基于 CSS3 实现支持 IE9animationString动画效果默认AMAP_ANIMATION_NONE可选AMAP_ANIMATION_DROP掉落、AMAP_ANIMATION_BOUNCE弹跳titleString鼠标滑过时的文字提示clickableBoolean是否可点击label{content, offset: [x, y]}文本标注content为标注内容offset为偏移量左上角偏移量为(0, 0)除文档所列外amap-marker.vue#L21-L48 的 props 列表还包含shadow、shape、extData、events、onceEvents等未在文档表格中展开的属性其中shape碰撞形状内部转换为AMap.MarkerShape与extData自定义数据可经$$getExtData()读回在高德原生 API 中同样有效。两个属性的转换与定制机制源码证据position/offset/label的数组→高德对象转换。amap-marker.vue#L60-L90 通过converters将数组转为高德对象例如label的offset经 toPixel 转为AMap.Pixelposition则命中 commonConvertMap 中的toLngLat。反向读取时$$getPosition()/$$getOffset()通过 lngLatTo / pixelTo 把高德对象转回[lng, lat]/[x, y]数组因此你始终可以按普通数组与标记交互。zIndex与visible的定制 handler。高德AMap.Marker的可见性 setter 是show()/hide()而非setVisiblezIndex 的 setter 为setzIndex组件在 handlers 中显式声明handlers: { zIndex(index) { this.setzIndex(index); }, visible(flag) { flag false ? this.hide() : this.show(); } }getHandlerFunregister-component.js#L44-L50优先使用组件自定义 handler其次按驼峰规则回退到set 大写属性名最后回退到setOptions。这套查找链是 vue-amap 所有覆盖物组件动态响应能力的公共底座。五、自定义内容渲染content、template、vnode、contentRender 与插槽这是 marker 组件能力最丰富的部分。四种内容来源最终都归一为高德content参数——propsRedirect 声明了重定向关系propsRedirect: { template: content, vnode: content, contentRender: content }各自在 converters 中的转换实现方式版本源码转换适用场景content-直接传字符串/DOM简单的静态 HTMLtemplatev0.4.0compile(tpl, self)生成独立 Vue 实例需要模板字符串 事件绑定、数据访问vnodev0.4.2mountedVNode(vNode)挂载 VNode已有 VNode 的场景contentRenderv0.4.3mountedRenderFn(renderFn, self)render 函数可返回组件 VNode如示例中的exampleComponents默认插槽v0.4.5见下文在模板中直接书写子元素compile.js 的实现揭示了这些方式的工作细节compile(tpl, vm)通过Vue.compile(tpl)编译模板并从父链上继承methods、computed、data、filters因此 marker 内的模板可以直接调用外层组件的方法和访问数据mountedVNode/mountedRenderFn则是把 VNode 或 render 函数包进一个独立new Vue({ render }).$mount()实例取其$el交给高德作为content。插槽渲染的实现同样值得关注amap-marker.vue#L101-L139 在created中创建一个tmpVM空 Vue 实例render中把$slots.default赋给tmpVM.node触发更新随后__initComponent将tmpVM.$refs.node作为content传入。组件销毁时destroyed 钩子会$destroy()掉tmpVM与$customContent避免自定义内容实例泄漏。一个完整的插槽示例继承自 官方自定义内容文档el-amap vidamapDemo :centercenter :zoomzoom el-amap-marker v-for(marker, index) in markers :positionmarker.position :vidindex div :styleslotStyle bHello {{ count }} times/b button clickonClickAdd/button /div /el-amap-marker /el-amap其中onClick更新count后插槽内容会随 Vue 响应式实时更新这是普通content字符串做不到的。六、ref 帮助方法与 AMapManager文档提供一组无副作用的同步帮助方法前缀$$与内部属性$amapComponent区分实现位于 amap-marker.vue#L121-L132 与 register-component.js#L190-L192函数返回说明$$getInstance()AMap.Marker获取高德 marker 原生实例$$getPosition()[lng, lat]获取位置已转换为普通数组$$getOffset()[x, y]获取偏移像素坐标$$getExtData()any获取用户自定义属性对应extData入参典型用法// 通过 ref 拿到原生实例直接调用高德 API如 moveTo 动画 this.$refs.myMarker.$$getInstance().moveTo([121.5, 31.2], 500); const pos this.$refs.myMarker.$$getPosition(); // [lng, lat]此外设置vid后实例还会被注册进 AMapManager由registerToManager完成register-component.js#L139-L144可在不持有 ref 的情况下全局取用import { AMapManager } from vue-amap; const amapManager new AMapManager(); // el-amap :amap-manageramapManager 内任意 vid 的 marker amapManager.getComponent(component-marker); // AMap.Marker 实例需要amapManager时须将其作为amapManagerprop 传给el-amapamap.vue#L209-L224 中setMap并广播AMAP_READY_EVENT给所有子组件。七、事件体系文档列出 marker 支持的全部事件参数均为高德MapsEvent其中moveend/movealong由高德动画方法触发事件说明click鼠标左键单击事件dblclick鼠标左键双击事件rightclick鼠标右键单击事件mousemove鼠标移动mouseover/mouseout鼠标移近 / 移出点标记时触发mousedown/mouseup鼠标在点标记上按下 / 抬起时触发dragstart/dragging/dragend开始拖拽 / 拖拽移动中 / 拖拽结束moveendmoveTo动画结束也可由moveAlong触发movealongmoveAlong动画一次后触发touchstart/touchmove/touchend触摸开始 / 移动中 / 结束仅适用移动设备实现机制事件不直接写在模板上而是通过events/onceEvents属性以对象形式传入如第二节示例中的marker.events。registerEvents 遍历events键名经 EventHelper.addListener 逐个绑定到高德实例并维护{ instance: { eventName: [...listeners] } }映射表以便统一清理。两个值得注意的行为事件对象本身也是响应式的setPropWatchers 对eventsprop 做了特判——监听变化后先unregisterEvents()再registerEvents()即整体解绑重绑。因此在 data 中修改events回调函数会生效但建议将回调放在methods中避免重复创建。销毁即清理混入destroyed钩子调用 clearListeners 移除该实例上的全部监听防止v-for增删 marker 时出现幽灵回调。events对象还保留了特殊的init键register-component.js#L186高德实例就绪后执行events.init(instance, map, amapManager)可用于立即操作原生实例如marker.setMap、moveTo等。八、注册流程全链路源码纵深把以上内容串起来el-amap-marker从挂载到就绪的完整调用链是mounted等待高德 SDK 加载完成lazyAMapApiLoaderInstance.load()从父组件取$amap地图实例取不到则监听AMAP_READY_EVENT后重试该事件由 amap.vue#L216-L219 在地图创建后向$children广播register()→convertProps()把所有 props 按propsRedirect重定向、按converters/commonConvertMap转换position→AMap.LngLat等并附带map: this.$amap__initComponent(options)amap-marker.vue#L113-L119若有默认插槽则将其 DOM 注入options.content然后new AMap.Marker(options)registerRest(instance)依次registerEvents()绑定events/onceEvents→initProps()补齐visible等无法在构造期生效的属性→setPropWatchers()为每个动态 prop 建立$watch变化时自动调用对应 setter→registerToManager()按vid注册。理解了这条链路就能推断出使用边界响应式只覆盖动态属性有 setter 或有定制 handler 的 prop内容类属性template/vnode/contentRender的转换发生在初始化阶段若需整体替换自定义内容实践中更稳妥的做法是改变vid/key强制重建 marker 实例。九、常见场景速查拖拽后同步坐标events.dragend中this.markers[i].position [e.lnglat.lng, e.lnglat.lat]第二节示例。图标与内容取舍content有效时icon被覆盖二者只选其一icon支持本地图标地址。文本标注label传{ content: 店铺, offset: [0, 0] }offset为相对标注左上角的像素偏移。动画animation: AMAP_ANIMATION_DROP掉落、AMAP_ANIMATION_BOUNCE弹跳配合autoRotation可做沿路径航行的航点标记。与原生 SDK 混用events.init(o {...})或amapManager.getMap()拿到AMap.Map后可自由创建原生覆盖物详见 compatible.md。十、参考资料仓库内路径文件说明src/docs/zh-cn/coverings/marker.md点标记官方文档本文主体来源src/docs/zh-cn/examples/coverings/marker-custom-content.mdcontent / template / render / 插槽四种渲染示例src/lib/components/amap-marker.vuemarker 组件实现converters / handlers / 插槽 /$$方法src/lib/mixins/register-component.js注册、props 转换、事件绑定、响应式 watcher 的公共混入src/lib/utils/compile.jstemplate / vnode / contentRender 的编译实现src/lib/utils/convert-helper.jsposition/offset 等数组与高德对象互转src/lib/utils/event-helper.js高德事件监听与批量清理src/lib/managers/amap-manager.jsAMapManager实例注册与获取test/unit/specs/compoents/amap.spec.js地图实例与 AMapManager 的单元测试验证events.init与getMap()行为赞分享前端UI组件GIS【免费下载链接】vue-amap 基于 Vue 2.x 和高德地图的地图组件项目地址https://gitcode.com/gh_mirrors/vu/vue-amap点击查看免费下载相关推荐vue-amap 圆点标记el-amap-circle-marker组件完全指南响应式属性、事件与源码级原理vue amap 圆点标记el amap circle marker组件完全指南响应式属性、事件与源码级原理 本指南以 vue amap 官方文档 cir前端UI组件GISvue-amap 椭圆覆盖物 el-amap-ellipse 实战从基础示例到属性、事件与响应式实现的源码级解析vue amap 椭圆覆盖物 el amap ellipse 实战从基础示例到属性、事件与响应式实现的源码级解析 本文以 vue amap 官方文档中的椭圆覆前端UI组件GISvue-amap 图片覆盖物实战指南el-amap-ground-image 的 bounds 配置、属性响应式与事件处理vue amap 图片覆盖物实战指南el amap ground image 的 bounds 配置、属性响应式与事件处理 本篇基于 vue amap基于前端UI组件GIS创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考