Efficient and convenient selection of provinces and municipalities——Practical strategy for the selection and packaging of Area provinces and municipalities

foreword

The selection of provinces and cities is a common functional requirement in many mobile applications, and the area component of vant has provided us with a very useful selection scheme. However, in some scenarios, we need to re-encapsulate the area and provide a more customized function of selecting provinces and districts to meet more specific business needs. This article will introduce how to re-encapsulate area in vant , and provide some practical encapsulation techniques and methods to help you achieve a more perfect selection of provinces and cities.


Implementation ideas

  1. First define a subcomponent page to encapsulate the selector;
  2. Introduce and register the encapsulation component (subcomponent) in the parent component (the page used), and then use it in the page. In the parent component, bind multiple attributes to the label (registered component name), and the attribute needs to be passed to mount The value of is received by propsreceiving data in the subcomponent (encapsulation file);
  3. Customize the determined event in the child component. After calling this event, the child component sends this.$emit('自定义事件名',要传递的数据)the data that the parent component can listen to, and finally the parent component listens to the child component event, calls the event and receives the passed data.

Install

vantThe official provides a default data of provinces and cities, which can be @vant/area-dataimported through:

npm i @vant/area-data

defined parameters

parameter describe
selectValue bind valuemodel
keyValue bound keyfield
columnsNum bound valuefield
rules The bound optiondata source
required Whether to display red *check

package file

<template>
  <div>
    <van-field v-model="textValue" v-bind="$attrs" :name="$attrs.name" :placeholder="placeholder" :rules="rules" :required="required"
      :readonly="readonly" :is-link="islink" @click="show = !show" />
    <van-popup v-model="show" position="bottom" :overlay="true" :close-on-click-overlay="true">
      <van-area :area-list="areaList" :columns-num="columnsNum" :columns-placeholder="columnsplaceholder" @confirm="onConfirm"
        @cancel="show = !show" />
    </van-popup>
  </div>
</template>

<script>
import {
      
       areaList } from "@vant/area-data";
export default {
      
      
  props: {
      
      
    required: {
      
      
      type: Boolean,
    },
    readonly: {
      
      
      type: Boolean,
    },
    islink: {
      
      
      type: Boolean,
    },
    columnsNum: {
      
      
      type: Number,
    },
    rules: {
      
      
      type: Array,
    },
    selectValue: {
      
      
      type: String,
    },
    keyValue: {
      
      
      //code 返回区县码  name 返回区县名称
      type: String,
    },
  },
  data() {
      
      
    return {
      
      
      areaList,
      show: false,
      textValue: "",
      selectOptions: [],
      placeholder: "",
      columnsplaceholder: ["请选择", "请选择", "请选择"],
      provinceList: null,
      cityList: null,
      countyList: null,
      province: "", //省
      city: "", //市
      county: "", //区县
    };
  },
  methods: {
      
      
    onConfirm(areaData) {
      
      
      // 判断打开选择器后是否必填省/市/区
      if (this.columnsNum == "1") {
      
      
        this.provinceOn(areaData);
      } else if (this.columnsNum == "2") {
      
      
        this.provinceCityOn(areaData);
      } else {
      
      
        this.provincesMunicipalitiesOn(areaData);
      }
    },
    // 省时必填校验
    provinceOn(areaData) {
      
      
      let province = areaData[0];
      if (province.name) {
      
      
      } else {
      
      
        this.$toast("请选择省");
        return;
      }
      this.acquireOn(areaData);
    },
    // 省市时必填校验
    provinceCityOn(areaData) {
      
      
      let province = areaData[0];
      let city = areaData[1];
      if (province.name) {
      
      
      } else {
      
      
        this.$toast("请选择省");
        return;
      }
      if (city.name) {
      
      
      } else {
      
      
        this.$toast("请选择市");
        return;
      }
      this.acquireOn(areaData);
    },
    // 省市区时必填校验
    provincesMunicipalitiesOn(areaData) {
      
      
      let province = areaData[0];
      let city = areaData[1];
      let area = areaData[2];
      if (province.name) {
      
      
      } else {
      
      
        this.$toast("请选择省");
        return;
      }
      if (city.name) {
      
      
      } else {
      
      
        this.$toast("请选择市");
        return;
      }
      if (area.name) {
      
      
      } else {
      
      
        this.$toast("请选择区");
        return;
      }
      this.acquireOn(areaData);
    },
    // 校验完后执行确定方法赋值name/code
    acquireOn(areaData) {
      
      
      // 获取选中name/code值
      let names = "";
      let codes = "";
      areaData.map((item, index) => {
      
      
        if (!item) {
      
      
          return "";
        }
        if (index > 0) {
      
      
          names += "/" + item.name;
          codes += "/" + item.code;
        } else {
      
      
          names += item.name;
          codes += item.code;
        }
      });
      if (this.keyValue == "code") {
      
      
        this.textValue = codes;
      } else {
      
      
        this.textValue = names;
      }
      this.show = !this.show;
      this.$emit("confirm", this.textValue);
    },
    //通过code 值获取地区name
    getNameByCode(value, list) {
      
      
      let name = "";
      if (!value) {
      
      
        return;
      }
      Object.keys(list).forEach((key) => {
      
      
        if (value.toString() == key.toString()) {
      
      
          name = list[key];
        }
      });
      return name;
    },
    //地区回显
    getValue(type) {
      
      
      if (!this.selectValue || !this.selectValue.length) {
      
      
        //如果 value传值不存在
        this.textValue = "";
        return;
      }
      let selectList = this.selectValue.split("/");
      let provinceName,
        cityName,
        countyName = "";
      switch (type) {
      
      
        case "code":
          //如果父级传值是 code
          if (Number(this.columnsNum) == 1) {
      
      
            //省
            provinceName = this.getNameByCode(selectList[0], this.provinceList);
            this.textValue = provinceName;
          } else if (Number(this.columnsNum) == 2) {
      
      
            //省
            provinceName = this.getNameByCode(selectList[0], this.provinceList);
            //市
            cityName = this.getNameByCode(selectList[1], this.cityList);
            this.textValue = provinceName + "/" + cityName;
          } else {
      
      
            //省
            provinceName = this.getNameByCode(selectList[0], this.provinceList);
            //市
            cityName = this.getNameByCode(selectList[1], this.cityList);
            //区
            countyName = this.getNameByCode(selectList[2], this.countyList);
            this.textValue = provinceName + "/" + cityName + "/" + countyName;
          }
          break;
        case "name":
          //如果父级传值是 name
          this.textValue = this.selectValue;
          break;
      }
    },
  },
  watch: {
      
      
    // json数据
    areaList: {
      
      
      handler(newVal) {
      
      
        if (newVal) {
      
      
          let length = Object.keys(newVal).length;
          if (length) {
      
      
            this.cityList = newVal.city_list;
            this.countyList = newVal.county_list;
            this.provinceList = newVal.province_list;
          }
        }
      },
      immediate: true,
      deep: true,
    },
    // 控制选择完整省市区还是部分
    columnsNum: {
      
      
      handler(newVal) {
      
      
        switch (newVal) {
      
      
          case 1:
            this.placeholder = "省";
            this.columnsplaceholder = ["请选择"];
            break;
          case 2:
            this.placeholder = "省/市";
            this.columnsplaceholder = ["请选择", "请选择"];
            break;
          default:
            this.placeholder = "省/市/区";
            this.columnsplaceholder = ["请选择", "请选择", "请选择"];
        }
      },
      immediate: true,
    },
    selectValue: {
      
      
      handler(newValue) {
      
      
        this.$nextTick(() => {
      
      
          if (this.keyValue) {
      
      
            this.getValue(this.keyValue);
          }
        });
      },
      immediate: true,
    },
    keyValue: {
      
      
      handler(newValue) {
      
      
        if (newValue) {
      
      
          this.getValue(newValue);
        }
      },
      immediate: true,
    },
  },
};
</script>

use file

<template>
  <div>
    <van-form validate-first>
      <AreaSelect name="cjPovo" label="车辆注册地" :selectValue="cjPovo" :readonly="true" :keyValue="`name`" :columnsNum="3"
        @confirm="areaConfirm" :required="true" :rules="rules.cjPovo" />
      <div class="btnBomBox">
        <van-button round size="small" block @click="submitOn" type="info">提交</van-button>
      </div>
    </van-form>
  </div>
</template>

<script>
import AreaSelect from "@/components/areaSelect/index";
export default {
      
      
  components: {
      
      
    AreaSelect,
  },
  data() {
      
      
    return {
      
      
      cjPovo: "",
      rules: {
      
      
        cjPovo: [
          {
      
      
            required: true,
            message: "请选择车辆注册地",
          },
        ],
      },
    };
  },
  methods: {
      
      
    // 点击确定
    areaConfirm(data) {
      
      
      this.cjPovo = data;
    },
    // 提交
    submitOn() {
      
      
      console.log(this.cjPovo);
    },
  },
};
</script>

<style scoped>
.btnBomBox {
      
      
  padding: 0px 16px;
  display: flex;
  justify-content: center;
}
</style>

achieve effect

insert image description here

Guess you like

Origin blog.csdn.net/Shids_/article/details/131087972