对地图选址组件的扩展

144 阅读4分钟

对地图选址组件的扩展

高德地图 element-ui vue2

前言

​ 在上一篇文章《封装了一个简单易懂的地图选址组件》的基础上,给添加了省市区联动的功能。实现了打开地图之前可以根据省市区域的选择进行一个初步定位,在选址结束后结果可以同步至省市区的选择上。

具体效果

根据省市区的选择进行地图初始化

选址初始化前.gif

选之后跟区域选择组件进行联动

选址后联动.gif

1. 区域选择组件

区域选择组件使用的是element ui的级联选择器,数据来源是网上下载的。

有关这个级联选择器:

changeArea(data) {
    // change事件抛出最后一项的原始数据
    // console.log(data);
    // console.log(this.$refs.baseAreaSelect.panel.getNodeByValue(data[data.length - 1]));
    const lastSourceNode = this.$refs.baseAreaSelect.panel.getNodeByValue(
        data[data.length - 1]
    );  // 不使用getCheckedNodes
    // console.log(lastSourceNode);
    const lastSourceData = lastSourceNode ? lastSourceNode.data : {};
    this.$emit("update:adcode", lastSourceData.id);
    this.$emit("area-change", lastSourceData);
},
  1. 他的绑定值我研究了好久,好像都是绑定你设置的value值组成的数组,也就是没办法同时获取到value跟label的内容。
  2. 如果你设置了可以搜索filterable,那么在change的时候调用getCheckedNodes获取选择节点的数组方法会有点问题,所以这里直接调用了源码里的方法。

选择地址后的联动是通过监听watch prop来实现的

  watch: {
    adcode(newValue, oldValue) {
      if (newValue && newValue.length === 6) {
        // 根据adcode遍历出省市区
        let result = [];
        let provinceData = null;
        let urbanData = null;
        let townshipData = null;
        // 确定省份
        const provinceId = newValue.slice(0, 2) + "0000";
        provinceData = sourceData.find((item) => item.id === provinceId);
        if (provinceData) {
          result.push((provinceData[this.valueFormat] || ""));
          urbanData = provinceData.children || [];
        }
        // 确定市区
        if (urbanData && urbanData.length) {
          const urbanId = newValue.slice(0, 4) + "00";
          let urbanDatas = urbanData.find((item) => item.id === urbanId);
          if(!urbanDatas) {  // 考虑无三级行政区域的
            urbanDatas = urbanData.find((item) => item.id === newValue);
          }
          result.push((urbanDatas[this.valueFormat] || ""));
          townshipData = (urbanDatas || {}).children || [];
        }
        // 确定乡镇
        if (townshipData && townshipData.length) {
          const township = townshipData.find((item) => item.id === newValue);
          result.push((township[this.valueFormat] || ""));
        }
        this.cascaderValue = result;
      }
    },
  },

这里没使用多重for循环,而是通过分步循环来实现,如果你觉得复杂可以自己改一下。

2. 组件组合

这一部分就是将区域选择组件和上一篇文章中提到的地图选址组件放到form表单中进行了组合。

样式方面没有进行额外的扩展配置,如果有需要就自己改一下。

地图选址组件的初始化位置是优先经纬度的,如果想要优先adcode,就自己改下。

表单校验方面做的是要么全部都校验要么就不校验。

因为想做到可以简单使用所以没有进行太多额外设置,如果有需要可以根据自己的业务逻辑进行修改。

    // 打开定位弹窗(经纬度优先)
    openAMapSelect() {
      const options = {
        zoom: 15,
      };
      if (this.form.lat && this.form.lng) {
        options.center = [this.form.lng, this.form.lat];
      } else if (this.form.adcode) {
        options.cityId = this.form.adcode;
      }
      this.$refs.aMapSelect.init(options);
    },
说明文档及源码
  • 区域选择组件说明文档
Attribute
参数说明类型可选值默认值
v-model绑定值Array
adcode城市idString
valueFormat数据源中对应的键名Stringext_name/id/nameext_name
  1. adcode城市id是联动的,即更改adcode值时,v-model绑定的值也会改变。
  2. valueFormat其实还有其他值可选,参考源数据。
Events
事件名称说明回调参数
area-changechange时触发,回调参数为最后一项的源数据最后一项的源数据
  • 区域选择组件源码地址:码云
  • 联动地图选址表单组件说明文档
Attribute
参数说明类型可选值默认值
amapKey高德地图keyString
code高德地图密钥String
labelWidth同el-form的label-widthString80px
required是否全部必填Booleantrue
formData用于回显的表单数据Object{}

formData将被监听,并和组件中form进行对象合并,用于数据回显

Methods
方法名说明参数
getResult直接获取结果结果值
getValidateResult验证后获取结果(async/await函数)校验结果值
reset重置数据并重置表单校验结果

getResult返回值为一个对象,形式为{area:[], adcode:"", address:"", lat:"", lng:"" }

getValidateResult返回值为一个对象,形式为{ validateRes:校验结果, msg:未通过时的信息},校验通过时还有datas字段,内容为结果对象(如上)

  • 联动地图选址表单组件源码位置:码云
  • 相关链接

组件 | Element

参考手册-地图 JS API v2.0|高德地图API (amap.com)

2023/06/08更新
  • 新增数据回显props