地图级联选择框组件
效果图

代码:
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 },
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号