vue2 省市区联动组件封装

发布时间:2024年01月18日

在element ui中有级联选择器el-cascader,其实已经够用了,但是在实际需求中,发现el-cascader如果有三级,数据数组必须得三个才能完全展示,所以不符合实际需求,还是自定义封装吧

需求:省市区联动数组,有多少个显示多少个

这里使用element ui得el-select组件,思路是使用监听

布局

  <el-select
      ref="selectProvinces"
      v-model="provinces.value"
      placeholder="请选择省"
      :disabled="disableds.provinces"
    >
      <el-option
        v-for="province in provinces.children"
        :key="province.value"
        :label="province.label"
        :value="province.value"
      >
      </el-option>
    </el-select>
    <el-select
      ref="selectCitys"
      v-model="citys.value"
      placeholder="请选择市"
      :disabled="disableds.citys"
      :default-first-option="true"
      @change="changeCity"
    >
      <el-option
        v-for="city in citys.children"
        :key="city.value"
        :label="city.label"
        :value="city.value"
      >
      </el-option>
    </el-select>
    <el-select
      ref="selectAreas"
      v-model="areas.value"
      placeholder="请选择区"
      :disabled="disableds.areas"
    >
      <el-option
        v-for="area in areas.children"
        :key="area.value"
        :label="area.label"
        :value="area.value"
      >
      </el-option>
    </el-select>

传入省市区数组以及全部省市区json数据

也可不传

 props: {
    value: {
      type: Array,
      required: true
    },
    dataSource: Array,
  },

数据传入逻辑以及选择省市区联动逻辑

  data() {
    return {
      provinces: { label: "", value: "", children: [], index: "" },
      citys: { label: "", value: "", children: [], index: "" },
      areas: { label: "", value: "", children: [], index: "" },
      isForcibly: false,
    };
  },
  watch: {
    value: {
      handler: function() {
        //当传入的省市区数组为0时初始化 避免还存留上一个选择过的
        if (this.value.length == 0) {
          this.provinces = { label: "", value: "", children: [], index: "" };
          this.provinces.children = [...this.dataSource].map(item => {
            return { label: item.label, value: item.value };
          });
          this.citys = { label: "", value: "", children: [], index: "" };
          this.areas = { label: "", value: "", children: [], index: "" };
        }
        // 根据value渲染
        if (this.value && Array.isArray(this.value) && this.value.length > 0) {
          this.isForcibly = true;
          let keywords = ["provinces", "citys", "areas"];
          for (let index = 0; index < this.value.length; index++) {
            let keyword = keywords[index];
            this[keyword].value = this.value[index];
            if (index === 0) {
              this.provinces.index = this.dataSource.findIndex(
                item => item.value === this.value[index]
              );
              this.citys.children = this.dataSource[
                this.provinces.index
              ].children.map(item => {
                return { label: item.label, value: item.value };
              });
            }
            if (index === 1) {
              this.citys.index = this.dataSource[
                this.provinces.index
              ].children.findIndex(item => item.value === this.value[index]);
              if(this.citys.index !== -1) {
                this.areas.children = this.dataSource[
                  this.provinces.index
                ].children[this.citys.index].children.map(item => {
                  return { label: item.label, value: item.value };
                });
              } 
            }
          }

          this.$nextTick(() => (this.isForcibly = false));
        } else {
          this.provinces.value = "";
          this.citys.value = "";
          this.areas.value = "";
        }
      },
      immediate: true,
      deep: true
    },
    "provinces.value": {
      handler: function() {
        if (!this.provinces.value) return;
        this.provinces.index = this.dataSource.findIndex(
          item => item.value === this.provinces.value
        );
        if (this.isForcibly) return;
        this.citys = { label: "", value: "", children: [], index: "" };
        this.citys.children = this.dataSource[
          this.provinces.index
        ].children.map(item => {
          return { label: item.label, value: item.value };
        });
        this.areas = { label: "", value: "", children: [], index: "" };
        this.$emit("input", [this.provinces.value]);
      },
      deep: true
    },
    "citys.value": {
      handler: function() {
        if (!this.citys.value) return;
        this.citys.index = this.dataSource[
          this.provinces.index
        ].children.findIndex(item => item.value === this.citys.value);
        if (this.isForcibly) return;

        this.areas = { label: "", value: "", children: [], index: "" };
        this.areas.children = this.dataSource[this.provinces.index].children[
          this.citys.index
        ].children.map(item => {
          return { label: item.label, value: item.value };
        });
        this.$emit("input", [this.provinces.value, this.citys.value]);
      },
      deep: true
    },
    //监听区级选择 如果存在数据那么说明已经选择完毕
    "areas.value": {
      handler: function() {
        if (!this.areas.value || this.isForcibly) return;
        this.$emit("input", [
          this.provinces.value,
          this.citys.value,
          this.areas.value
        ]);
      },
      immediate: true,
      deep: true
    },
    },
  },
  created() {
    this.provinces.children = [...this.dataSource].map(item => {
      return { label: item.label, value: item.value };
    });
  },

效果如下:
在这里插入图片描述

文章来源:https://blog.csdn.net/wyq12138/article/details/135654882
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。