2025-06-19 13:33:54 +08:00

98 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- components/UrlSelect.vue -->
<template>
<el-select
v-bind="$attrs"
v-model="internalValue"
@change="$emit('change', $event)"
@blur="$emit('blur', $event)"
@focus="$emit('focus', $event)"
@clear="$emit('clear', $event)"
@visible-change="$emit('visible-change', $event)"
@remove-tag="$emit('remove-tag', $event)"
@scroll="$emit('scroll', $event)"
>
<template v-for="(_, name) in $slots" #[name]="scopedData">
<slot :name="name" v-bind="scopedData"> </slot>
</template>
<slot name="option-group">
<el-option v-for="item in options" :key="item[valueKey]" :label="item[labelKey]" :value="item[valueKey]" />
</slot>
</el-select>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
import request from '@/utils/axios';
// -------------- ① 定义要继承/自定义的 Props --------------
const props = defineProps({
modelValue: {
type: [String, Number, Array],
default: null,
},
url: {
type: String,
default: null,
},
params: {
type: Object,
default: () => ({}),
},
// 可按需让上层指定 label 字段名、value 字段名
labelKey: {
type: String,
default: 'label',
},
valueKey: {
type: String,
default: 'value',
},
responseParser: {
type: Function,
default: (res) => res.data.records, // 默认解析函数
},
});
// -------------- ② 定义要透传回父组件的 Events --------------
const emit = defineEmits(['update:modelValue', 'change', 'blur', 'focus', 'clear', 'visible-change', 'remove-tag', 'scroll']);
// -------------- ③ 内部双向绑定 --------------
// 用一个 ref 存储内部的值
const internalValue = ref(props.modelValue);
// 当 prop 变化时,同步到 internalValue
watch(
() => props.modelValue,
(newVal) => {
internalValue.value = newVal;
}
);
// 当 internalValue 变化时emit update:modelValue
watch(internalValue, (newVal) => {
emit('update:modelValue', newVal);
});
// -------------- ④ 选项列表 --------------
const options = ref([]);
// -------------- ⑤ 请求数据的函数 --------------
async function fetchOptions() {
// console.log('fetchOptions :>> ', props.url, props.params);
if (!props.url) return;
const res = await request.get(props.url, { params: props.params });
const records = props.responseParser(res);
if (Array.isArray(records)) {
options.value = records;
// console.log('option', options.value);
} else {
options.value = [];
console.error('UrlSelect解析后的数据不是数组');
}
}
// -------------- ⑥ 生命周期:组件挂载后立即拉一次数据 --------------
onMounted(() => {
fetchOptions();
});
</script>