element plus 级联选择器懒加载方式时的回显

92 阅读1分钟

注:需要后端配合,让他把选中区划的层级都查出来(这个对于后端来说很简单)。看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>