编写自定义组件 |
本节将以示范工程中的坐标获取范例为例介绍自定义组件的开发。请在继续阅读前,自行学习 Vue.js 的单文件组件和事件侦听器的知识。
坐标获取组件需实现在鼠标在地图上移动或点击,可实时展示坐标信息功能,如图1所示。另希望在属性设置面板可选择触发事件的模式是鼠标移动还是点击,如图2所示。
图1 功能组件面板 图2 属性组件面板
在新建的 Component.vue 单文件组件 <template></template>标签对中插入如下虚拟 DOM 代码:
<template>
<div :style="fontStyle" class="custom-component-container">
<h3 :style="{ color: textColor }">经纬度信息demo:</h3>
<div v-if="lngLat" class="coordinate-holder">
<div class="coordinate-item">
<label> 触发模式:</label>
<span>{{ optionsList[mode] }}</span>
</div>
<div class="coordinate-item">
<label> 经度:</label>
<span>{{ lngLat.lng }}</span>
</div>
<div class="coordinate-item">
<label> 纬度:</label>
<span>{{ lngLat.lat }}</span>
</div>
</div>
</div>
</template>
在<script></script>标签对中定义组件的名称、属性、虚拟 DOM 中用到的数据、方法、事件等。
如在本范例中定义的属性和数据如下所示:
<script>
export default {
name: 'CoordinatesPicker',
props: {
mode: {
type: String,
default: 'mousemove'
},
fontSize: {
type: String,
default: '18px'
},
textColor: {
type: String,
default: '#fff'
},
background: {
type: String,
default: '#333'
}
},
data() {
return {
lngLat: null,
optionsList: {
click: '点击',
mousemove: '鼠标移动'
},
pointsLen: 5
};
}
};
</script>
本示例需根据属性面板设置的事件触发模式相应的改变组件的交互行为,所以在 <script></script>中使用了 watch 侦听 props 中 mode 字段的变化。代码如下所示:
watch: {
mode() {
this.triggerMapEvent();
}
}
上述代码调用的 triggerMapEvent() 方法可根据监听到的 mode 的值是鼠标移动还是点击给地图组件添加或移除相应的事件监听。
若自定义的组件需要与地图组件交互,还需实现 loaded(map) 和 removed(map)方法。接口介绍如下:
接口名 | 类型 | 参数 | 功能描述 |
loaded(map) | Fuction | map | 该方法在当前组件关联的地图加载完成时,即地图实例初始化完成后被调用。在该方法中可编写获取到 map 实例后,与 map 相关的交互操作。 |
removed(map) | Fuction | map | 该方法在当前组件关联的地图被销毁前被调用。在该方法中应当清除与 map 相关的操作,如:清除添加过的图层、移除添加在地图上的监听器、重置与 map 相关的变量等。 |
如本范例中,在 loaded(map) 中为关联地图添加了鼠标移动或单击的事件,在 removed(map) 中移除了侦听的事件、并将相关变量置空。代码如下所示:
loaded(map) {
this.map = map;
map.on(this.mode, this.showCoors);
},
removed() {
this.map.off(this.mode, this.showCoors);
this.map = null;
this.lngLat = null;
}
在 <style></style>标签对中定义组件 DOM 使用的样式。如步骤1中使用的样式 class 定义如下:
<style lang="css" scoped>
.custom-component-container {
padding: 8px;
}
h3 {
border-bottom: 2px solid #1890ff;
display: inline-block;
padding-bottom: 6px;
font-weight: 600;
}
.coordinate-holder {
padding: 0 10px;
}
.coordinate-item {
margin: 10px 0;
display: flex;
}
.coordinate-item label {
width: 35%;
}
.coordinate-item span {
flex: 1;
}
</style>
至此,功能组件的代码已编写完成。完整代码,请自行查阅范例。
若您的自定义组件无需支持在属性面板设置属性的功能,则无需编写属性组件。
编写属性组件的流程同上述编写功能组件。需要注意的是属性组件 Setting.vue 中定义的 props 对象应对应于功能组件 Component.vue 中定义的 props 对象。且每一个配置项的改动需要分发($emit)change 事件,值需以 key-value 键值对形式进行传递。代码如下所示:
<template>
<div class="custom-text-setting">
<div class="sm-setting-panel">
<div class="sm-setting-panel__header">触发模式:</div>
<a-select
class="sm-setting-panel__content"
:value="mode"
:options="optionsList"
:getPopupContainer="triggerNode => triggerNode.parentNode"
@change="val => handleChange({ mode: val })"
/>
</div>
<div class="sm-setting-panel">
<div class="sm-setting-panel__header">字体大小:</div>
<div class="sm-setting-panel__content">
<a-input :value="fontSize" @change="e => handleChange({ fontSize: e.target.value })" />
<span class="sm-setting-unit">像素</span>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
mode: String,
fontSize: [String, Number],
textColor: String,
background: String
},
data() {
return {
optionsList: [
{
label: '点击',
value: 'click'
},
{
label: '鼠标移动',
value: 'mousemove'
}
]
};
},
methods: {
handleChange(data) {
this.$emit('change', data);
}
}
};
</script>
地图大屏还提供了组件的部分基础样式属性,如上述代码虚拟 DOM 元素用到的 sm- 前缀的样式类,详细介绍如下:
至此,属性组件的代码已编写完成。完整代码,请自行查阅范例。