地图级联选择框组件

效果图

 

 

 代码:

html:

<template>
    <div class="cascader-container">
        <el-select placeholder="省"
                   class="select-item"
                   v-model="selectedValue[0].adcode"
                   @change="onChange('provice')">
            <el-option v-for="item in distract"
                       :key="item.adcode"
                       :label="item.name"
                       :value="item.adcode" />
        </el-select>
        <el-select placeholder="市"
                   no-data-text="请先选择省"
                   class="select-item"
                   v-model="selectedValue[1].adcode"
                   @change="onChange('city')">
            <el-option v-for="item in cityList"
                       :key="item.adcode"
                       :label="item.name"
                       :value="item.adcode" />
        </el-select>
        <el-select placeholder="区/县"
                   no-data-text="请先选择市"
                   class="select-item"
                   v-model="selectedValue[2].adcode"
                   @change="onChange('area')">
            <el-option v-for="item in areaList"
                       :key="item.adcode"
                       :label="item.name"
                       :value="item.adcode" />
        </el-select>
    </div>
</template>

js

<script>
// 通过接口获取地理位置信息 import { getAreaList } from '@/api/basic';
/* 使用手册: 1. v-model数组最多为三个 v-model="[{ abcode: 'xxx', name: 'xxx' }, { abcode: 'xxx', name: 'xxx' }, { abcode: 'xxx', name: 'xxx' }]" 2. 事件 2.1 change事件, 参数为当前选中的数据 */ export default { name: 'cascader', created() { this.watchValueOnce(); this.getAreaList(); }, props: { value: { type: Array, default: () => [] } }, data() { return { // 省市区 distract: [], // 选中的数据 selectedValue: new Array(3).fill({ adcode: '', name: '' }) } }, computed: { // province() { return this.value[0] || {}; }, // city() { return this.value[1] || {}; }, // area() { return this.value[2] || {}; }, // 市列表 cityList() { let result = this.distract.find(item => item.adcode === this.province.adcode) || {}; return result.districts || []; }, // 区县列表(处理重复问题) areaList() { let result = this.cityList.find(item => item.adcode === this.city.adcode) || {}; let districts = result.districts || []; return districts.map((item, idx) => { if (item.adcode === this.city.adcode) { return { ...item, adcode: idx } } return item; }); }, distractMap() { return { ...this.getDistractMap(this.distract), ...this.getDistractMap(this.cityList), ...this.getDistractMap(this.areaList) }; } }, methods: { getDistractMap(distracts = []) { return distracts.reduce((map, item) => { map[item.adcode] = item; return map; }, {}) }, // 获取省市区 async getAreaList() { let result = await getAreaList(); let distract = (result.data || {}).districts || []; if (distract.length > 0) { this.distract = distract[0].districts || []; this.$emit('input', this.getEmitVale()); } }, // 只监听一次value watchValueOnce() { const unWatch = this.$watch('value', () => { let value = this.value || []; if (value.length === 3) { let city = value[1] || {}; let area = value[2] || {}; city = typeof city === 'string' ? { adcode: city } : city; area = typeof area === 'string' ? { adcode: area } : area; if (city.adcode == area.adcode) { value = value.slice(0, 2); } } this.selectedValue = this.selectedValue.map((item, idx) => { let valueItem = value[idx]; if (typeof valueItem === 'string' || valueItem === void 0) { return { adcode: valueItem || '', name: '' } } return valueItem; }); this.$emit('input', this.getEmitVale()); unWatch(); }); }, // 获取emit数据 getEmitVale(type) { if (type === 'provice') { this.selectedValue = [this.selectedValue[0], {}, {}]; } if (type === 'city') { this.selectedValue = [this.selectedValue[0], this.selectedValue[1], {}]; } let selectedValue = this.selectedValue.filter(({ adcode }) => { return adcode !== void 0 && `${ adcode }`.length !== 0; }); let emitValue = selectedValue.map((item, idx) => { let { adcode } = item; let { name = '' } = this.distractMap[adcode] || {} adcode = `${ adcode }`.length === 1 ? selectedValue[idx - 1].adcode : adcode; return { ...item, adcode, name } }); return emitValue; }, // 切换 onChange(type) { let result = this.getEmitVale(type); this.$emit('input', result); this.$emit('change', result); } } } </script>

css:

<style lang="less">
.cascader-container {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    .select-item {
        .el-input__inner {
            padding-left: 8px;
            padding-right: 18px;
        }
        .el-input__suffix {
            right: 0;
            .el-input__icon {
                width: 20px;
                font-size: 10px;
            }
        }
        .el-input {
            position: relative;
            z-index: 1
        }
        &:nth-child(1) {
            .el-input__inner {
                border-radius: 4px 0 0 4px;
            }
        }
        &:nth-child(2) {
            .el-input {
                z-index: 0;
                left: -1px;
                width: calc(100% + 3px);
                &.is-focus {
                    z-index: 2;
                }
            }
            .el-input__inner {
                border-radius: 0;
            }
        }
        &:nth-child(3) {
            .el-input__inner {
                border-radius: 0 4px 4px 0;
            }
        }
    }
}
</style>

 父组件引用:

 

<el-form-item label="居住地址" prop="orderAnjiApplicantAddDto.residentialStreet">
      <div class="address">
            <CascaderDistract @change="inputResidentialAddress" :value="residentialAddress"/>
            <el-input placeholder="请输入详细地址" class="unit-input control-input" v-model="form.orderAnjiApplicantAddDto.residentialStreet"></el-input>
      </div>
</el-form-item>

 

inputResidentialAddress是选择完的回调,会返回一个数组:【省,市,区】,

residentialAddress用来存放选择完后的数据
data:  
// 居住地地址
residentialAddress: [],
methods:
// 选择完位置后
  inputResidentialAddress(res){
     this.residentialAddress = res
  },

 

posted @ 2022-12-29 11:32  幻影之舞  阅读(58)  评论(0)    收藏  举报