注:需要后端配合,让他把选中区划的层级都查出来(这个对于后端来说很简单)。看80行的注释
.vue文件
<template>
<el-cascader
:teleported="false"
v-model="valueModel"
:props="propsData"
:options="options"
clearable
:disabled
filterable
popper-class="cascader-class"
@change="change"
ref="cascaderRef"
/>
</template>
<script setup>
import { ref, nextTick } from 'vue';
import { deptsList, systemAreas } from '@/api/modules/system';
defineOptions({
name: 'CustomCascader',
});
const props = defineProps({
disabled: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '请选择',
},
apiType: {
type: String,
default: 'area',
},
emitPath: {
type: Boolean,
default: true,
},
checkStrictly: {
type: Boolean,
default: true,
},
});
const valueModel = defineModel({ default: [] });
const nameModel = defineModel('name', { default: '' });
const cascaderRef = ref(null);
const change = (val) => {
valueModel.value = val === undefined ? '' : val;
nameModel.value = cascaderRef.value.presentText;
console.log(options.value);
};
const apiStore = {
dept: deptsList,
area: systemAreas,
};
const lazyLoad = async (node, resolve) => {
const { data } = node;
const result = await apiStore[props.apiType]({ id: data.id });
resolve(result?.data);
};
const propsData = reactive({
label: 'name',
value: 'id',
leaf: 'leaf',
lazy: true,
checkStrictly: props.checkStrictly,
emitPath: props.emitPath,
lazyLoad,
});
// ! 级联选择器的回显方法
// ! options 用来回显时的数据填充,
// ! 回显时需要根据后端返回的ids来调用接口。如 ids:"140000000000/170407172416",
const options = ref([]);
const echoData = async (str) => {
if (!str) return;
const ids = str.split('/').slice(0, str.split('/').length - 1);
let localData = [
{
name: '山西省',
id: '140000000000',
children: [],
leaf: false,
pid: '0',
},
];
const setChildData = (data, row) => {
data.forEach((item) => {
if (item.id === row.pid) {
item.children.push(row);
} else if (item.children && item.children.length) {
setChildData(item.children, row);
}
});
};
const echoDataApi = async (id) => {
const res = await apiStore[props.apiType]({ id });
if (res.code === 200) {
(res?.data || []).forEach((item) => {
setChildData(localData, item);
});
if (ids.length) {
await echoDataApi(ids.shift());
}
}
};
await echoDataApi(ids.shift());
options.value = localData;
nextTick(() => {
localData = null;
});
};
defineExpose({
echoData,
});
</script>
<style scoped lang="less"></style>