大概思路:
- 准备一个接口可以通过父Id,查询到下一级省市区街道的信息;如下方的getRegionListOne
- 确定后端的数据结构,需要在created里边处理数据回显逻辑
- el-cascader接收的数据格式是[‘’,‘’,‘’];后端的数据格式多为[{provinceId: ‘’, regionId: ‘’, cityId: ‘’}]
- 可以通过设置comType,来确定是省市区还是省市区街道,组件内完成逻辑处理。
直接上代码
<template>
<div class="areaLazy">
<el-cascader
v-model="currentChoose"
v-bind="_options"
:options="addressList"
:disabled="_options.disabled"
@change="handleChange"
/>
</div>
</template>
<script>
export default {
name: "addresscascaderlazy",
};
</script>
<script setup>
import { ref, computed, watch } from "vue";
import API from "@/api";
const emits = defineEmits([
"update:modelValue"
]);
const props = defineProps({
disabled: {
//禁用
type: Boolean,
required: false,
default: false,
},
options: {
type: Object,
default: () => {},
},
modelValue: {
type: [Array, Object],
default: () => ([]),
},
});
let id = 0;
// 设置option默认值,如果传入自定义的配置则合并option配置项
const _options = computed(() => {
const option = {
name: "multipartFiles",
comType: "provinceCityCountryRegion",
props: {
lazy: true,
lazyLoad(node, resolve) {
const { level, value } = node; // 获取当前node对象中的level, value属性
getArea(level, value, resolve)
},
}
};
option.disabled = props.disabled;
return Object.assign(option, props.options);
});
const levelTag = {
"provinceCityCountryRegion": 3,
"provinceCityCountry": 2,
"provinceCity": 1,
}
const currentChoose = ref([]);
const addressList = ref([]);
const addressOrigin = ref({}); // 省市区数据
const handleChange = (val) => {
console.log('handleChange', val)
if (!val.length) {
emits('update:modelValue', val)
return
}
if (_options.value?.props?.multiple) {
const arr = []
val.forEach(item => {
const obj = {}
obj.provinceId = item[0]
obj.provinceName = addressOrigin.value[0][item[0]]
obj.cityId = item[1]
obj.cityName = addressOrigin.value[1][item[1]]
obj.regionId = item[2]
obj.regionName = addressOrigin.value[2][item[2]]
obj.streetId = val[3]
obj.streetName = addressOrigin.value[3][val[3]]
arr.push(obj)
})
emits('update:modelValue', arr)
} else {
const obj = {}
obj.provinceId = val[0]
obj.provinceName = addressOrigin.value[0][val[0]]
obj.cityId = val[1]
obj.cityName = addressOrigin.value[1][val[1]]
obj.regionId = val[2]
obj.regionName = addressOrigin.value[2][val[2]]
obj.streetId = val[3]
obj.streetName = addressOrigin.value[3][val[3]]
emits('update:modelValue', obj)
}
}
const getArea = (level, value, resolve) => {
API.getRegionListOne({parentId: value}).then(async (res) => {
addressOrigin.value[level] = {}
const nodes = res.result.map(item => {
addressOrigin.value[level][item.id] = item.name
return {
value: String(item.id),
label: item.name,
leaf: level >= levelTag[_options.value?.comType],
}
})
resolve(nodes)
})
}
const created = () => {
if (!props.modelValue) {
return []
}
if (props.modelValue instanceof Array) {
currentChoose.value = props.modelValue.map(item => {
if (_options.value.comType === "provinceCityCountryRegion") {
return [ item.provinceId, item.cityId, item.regionId, item.streetId ]
}
if (_options.value.comType === "provinceCityCountry") {
return [ item.provinceId, item.cityId, item.regionId ]
}
return [ item.provinceId, item.cityId ]
})
} else {
if (_options.value.comType === "provinceCityCountryRegion") {
currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId, props.modelValue.streetId]
return
}
if (_options.value.comType === "provinceCityCountry") {
currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId, props.modelValue.streetId]
return
}
currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId]
}
}
// 省市区
// getaddressList();
watch(()=>props.modelValue, (val) => {
created();
})
</script>
<style lang="less">
.areaLazy {
.el-input__inner {
min-width: 350px;
}
}
</style>
再附一个非懒加载形式的
<template>
<div class="areaUnit">
<el-cascader
v-model="currentChoose"
v-bind="_options"
:options="addressList"
:disabled="_options.disabled"
@change="handleChange"
/>
</div>
</template>
<script>
export default {
name: "addresscascader",
};
</script>
<script setup>
import { ref, computed, watch } from "vue";
import API from "@/api";
const emits = defineEmits([
"update:modelValue"
]);
const props = defineProps({
disabled: {
//禁用
type: Boolean,
required: false,
default: false,
},
options: {
type: Object,
default: () => {},
},
modelValue: {
type: [Array, Object],
default: () => ([]),
},
});
// 设置option默认值,如果传入自定义的配置则合并option配置项
const _options = computed(() => {
const option = {
name: "multipartFiles",
comType: "provinceCityCountry",
};
option.disabled = props.disabled;
return Object.assign(option, props.options);
});
const currentChoose = ref([]);
const addressList = ref([]);
const addressOrigin = ref({});
// 处理省市区数据结构
const handleBase = (list, childrenList, stringBan) => {
return new Promise((resolve) => {
const address = []
if (childrenList) {
for (const key in list) {
const children = childrenList.filter(i => String(i.value).substring(0, stringBan) === String(key).substring(0, stringBan));
address.push({
value: key,
label: list[key],
children
})
}
} else {
for (const key in list) {
address.push({
value: key,
label: list[key]
})
}
}
resolve(address)
})
}
// 获取省市区
const getaddressList = () => {
API.getRegionList().then(async (res) => {
const { province_list, city_list, county_list } = res.result;
addressOrigin.value = { province_list, city_list, county_list }
if (_options.value.comType === "provinceCityCountry") {
const countyAddress = await handleBase(county_list)
const cityAddress = await handleBase(city_list, countyAddress, 4)
addressList.value = await handleBase(province_list, cityAddress, 2)
}
if (_options.value.comType === "provinceCity") {
const cityAddress = await handleBase(city_list)
addressList.value = await handleBase(province_list, cityAddress, 2)
}
})
}
const handleChange = (val) => {
if (!val.length) {
emits('update:modelValue', val)
return
}
if (_options.value?.props?.multiple) {
const arr = []
val.forEach(item => {
const obj = {}
obj.provinceId = item[0]
obj.provinceName = addressOrigin.value.province_list[item[0]]
obj.cityId = item[1]
obj.cityName = addressOrigin.value.city_list[item[1]]
obj.regionId = item[2]
obj.regionName = addressOrigin.value.county_list[item[2]]
arr.push(obj)
})
emits('update:modelValue', arr)
} else {
const obj = {}
obj.provinceId = val[0]
obj.provinceName = addressOrigin.value.province_list[val[0]]
obj.cityId = val[1]
obj.cityName = addressOrigin.value.city_list[val[1]]
obj.regionId = val[2]
obj.regionName = addressOrigin.value.county_list[val[2]]
emits('update:modelValue', obj)
}
}
const created = () => {
if (!props.modelValue) {
return []
}
if (props.modelValue instanceof Array) {
currentChoose.value = props.modelValue.map(item => {
if (_options.value.comType === "provinceCityCountry") {
return [ item.provinceId, item.cityId, item.regionId ]
}
return [ item.provinceId, item.cityId ]
})
} else {
if (_options.value.comType === "provinceCityCountry") {
currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId]
} else {
currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId]
}
}
}
// 省市区
getaddressList();
watch(()=>props.modelValue, (val) => {
console.log('modelValue', val)
created();
})
</script>