VUE实现公用组件省市区三级下拉联动的过程

由于很久没有更新博客和公众号了,找了点以前的资源,暂时发一下更新

准备js接口

 import request from '@/router/axios';

//获取省份
export const getProvinceDict = () => {
  return request({
    url: '/api/blade-system/canton/getProvince',
    method: 'get',
    params: {
    }
  });
}

//获取城市
export const getCityDict = (province) => {
  return request({
    url: '/api/blade-system/canton/getCity',
    method: 'get',
    params: {
      province
    }
  });
}

//获取地区
export const getAreaDict = (city) => {
  return request({
    url: '/api/blade-system/canton/getArea',
    method: 'get',
    params: {
      city
    }
  });
}

vue文件

定义好模版,参考element-ui的语法,完成3级联动,第一步很简单,难点主要在返回值和默认值

返回值的重点在于 this.$emit的使用。

callback(){
         this.$emit("ChangeValue",{province:this.province,city:this.city,area:this.area});
       }

客户端需要提供ChangeValue方法来回调,得到最终的返回值。

<avue-form  ref="optionForm" v-model="regForm" :option="optionprops" :inline="true">
      <template slot-scope="scope" slot="address">
          <provincial-cascade @ChangeValue="GetProvinceValue" provinceCode="430000" cityCode="430100" areaCode="430102"></provincial-cascade>
      </template>
    </avue-form>
GetProvinceValue(item){
     //  console.log(item);
     var provinceCode=item.province;
     var cityCode=item.city;
     var areaCode=item.area;
   }

对于默认值,不能直接传给对应的province、city、area,而要传递给另一个变量作为副本。 在load的过程中,如果发现默认值不为空,则手动触发(调用)一下change方法,最终达到回显的效果。

            provinceCode:"",
            cityCode:"",
            areaCode:"",

              if(this.provinceCode!=null)
              {
                this.changeProvince(this.provinceCode);
              }
               if(this.cityCode!=null)
            {
                this.changeCity(this.cityCode);
            }

               if(this.areaCode!=null)
            {
              this.changeArea(this.areaCode);
            }  

完整代码

<template>
  <el-row >

    <el-col :span="8">
   <el-select v-model="this.province" clearable @change="changeProvince">
     <el-option
       v-for="item in this.provinceData"
       :key="item.key"
       :label="item.name"
       :value="item.key">
     </el-option>
   </el-select>
    </el-col>
    <el-col :span="8">
  <el-select v-model="this.city" clearable @change="changeCity">
    <el-option
      v-for="item in this.cityData"
      :key="item.key"
      :label="item.name"
      :value="item.key">
    </el-option>
  </el-select>
    </el-col>
    <el-col :span="8">
  <el-select v-model="this.area" clearable @change="changeArea">
    <el-option
      v-for="item in this.areaData"
      :key="item.key"
      :label="item.name"
      :value="item.key">
    </el-option>
  </el-select>
    </el-col>
  </el-row>
</template>

<script>
  import {getProvinceDict,getCityDict,getAreaDict} from '@/api/util/provincialCascade';

    export default {
      props:["provinceCode","cityCode","areaCode"],
        name: "provincial-cascade",
      data(){
          return {
            provinceCode:"",
            cityCode:"",
            areaCode:"",
            province:"",
            city:"",
            area:"",
            provinceData:[],
            cityData:[],
            areaData:[]

          }
      },
      created(){

      },
      beforeMount(){
        this.loadProvince();
      },
      methods:{

          loadProvince(){
            getProvinceDict().then((res)=>{

              this.provinceData=res.data.data;
              if(this.provinceCode!=null)
              {
                this.changeProvince(this.provinceCode);
              }

            })
          },
        changeProvince(v){
          getCityDict(v).then(res=>{
            this.cityData=res.data.data;
            this.province=v;
            this.city="";
            this.area="";
            if(this.cityCode!=null)
            {
                this.changeCity(this.cityCode);
            }


            this.callback();
          })
        },
        changeCity(v){
          getAreaDict(v).then(res=>{
            this.areaData=res.data.data;
            this.city=v;
            this.area="";
            if(this.areaCode!=null)
            {
              this.changeArea(this.areaCode);
            }
            this.callback();

          })
        },
        changeArea(v){
            this.area=v;
           // this.$emit("getValue",{provice:this.provice,city:this.city,area:this.area})
          this.callback();
        },
        callback(){
          this.$emit("ChangeValue",{province:this.province,city:this.city,area:this.area});
        }


      }


    }
</script>

<style scoped>

</style>

后端接口

后台用的BLADEX框架,公司已经买了永久授权了。当然大家如果感兴趣的话,可以去找BLADEX源码(https://bladex.cn/#/)去学习研究,也可以做一下这几个后台接口,试一下代码效果。 后台接口按照字典格式返回数据,基本上就没问题的。

接口地址:

/api/blade-system/canton/getProvince

/api/blade-system/canton/getCity

/api/blade-system/canton/getArea

更多方法

这个是我2020年的笔记,记录的一种方式,时间过去也有三四年了,可能技术发生了很多变化,如果大家有更好的方式和方法,也可以介绍给我学习一下,欢迎大家多多交流更多的技术方法。