在Vue 3项目里,使用Fetch API从后端获取动态数据填充下拉菜单是高频操作,而数据转换环节直接决定了下拉菜单能否正常展示选项,是开发过程中需要重点关注的部分。

Fetch API 获取下拉菜单数据的基础流程
首先我们需要通过Fetch API向后端接口发起请求,获取原始的下拉菜单数据,通常后端返回的数据格式是JSON数组,可能包含id、name等字段,但下拉菜单需要的选项格式往往和原始返回数据有差异。
基础的请求代码如下:
// 定义获取下拉菜单数据的函数
const fetchDropdownData = async () => {
try {
// 发起Fetch请求
const response = await fetch('https://api.ipipp.com/dropdown/list');
// 判断请求是否成功
if (!response.ok) {
throw new Error('请求失败,状态码:' + response.status);
}
// 解析JSON数据
const rawData = await response.json();
return rawData;
} catch (error) {
console.error('获取数据失败:', error);
return [];
}
};
数据转换的核心关键点
1. 格式适配转换
大部分UI组件库的下拉菜单选项要求数据格式为{ label: '显示文本', value: '对应值' }的形式,而后端返回的原始数据可能是{ id: 1, name: '选项一' },这时候就需要做格式转换。
转换代码示例:
// 原始数据转换函数
const transformData = (rawList) => {
// 校验原始数据是否为数组
if (!Array.isArray(rawList)) {
return [];
}
// 映射转换格式
return rawList.map(item => {
return {
label: item.name, // 显示文本对应原始数据的name字段
value: item.id // 选项值对应原始数据的id字段
};
});
};
2. 空值与异常数据处理
原始数据中可能存在字段缺失、值为null或者undefined的情况,直接转换会导致下拉菜单渲染异常,需要在转换时做兜底处理。
优化后的转换函数:
const transformData = (rawList) => {
if (!Array.isArray(rawList)) {
return [];
}
return rawList.map(item => {
// 兜底处理,避免字段缺失导致报错
const label = item.name || '未知选项';
const value = item.id ?? '';
return { label, value };
});
};
3. 数据类型校验
如果后端返回的value字段是数字类型,而下拉菜单需要字符串类型的value,或者反过来,就需要做类型转换,避免后续表单提交时出现类型不匹配的问题。
带类型转换的示例:
const transformData = (rawList) => {
if (!Array.isArray(rawList)) {
return [];
}
return rawList.map(item => {
return {
label: String(item.name || '未知选项'),
// 将id转为字符串类型
value: String(item.id ?? '')
};
});
};
Vue 3 中完整的使用示例
结合Vue 3的响应式API,完整的下拉菜单数据填充代码如下:
<template>
<div>
<select v-model="selectedValue">
<option value="">请选择</option>
<option
v-for="item in dropdownOptions"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</option>
</select>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
// 定义响应式数据
const dropdownOptions = ref([]);
const selectedValue = ref('');
// 数据转换函数
const transformData = (rawList) => {
if (!Array.isArray(rawList)) {
return [];
}
return rawList.map(item => {
return {
label: String(item.name || '未知选项'),
value: String(item.id ?? '')
};
});
};
// 获取数据的函数
const fetchDropdownData = async () => {
try {
const response = await fetch('https://api.ipipp.com/dropdown/list');
if (!response.ok) {
throw new Error('请求失败');
}
const rawData = await response.json();
// 转换数据并赋值给响应式变量
dropdownOptions.value = transformData(rawData);
} catch (error) {
console.error('获取数据失败:', error);
dropdownOptions.value = [];
}
};
// 组件挂载时发起请求
onMounted(() => {
fetchDropdownData();
});
</script>
常见注意事项
- 转换前一定要校验原始数据是否为数组,避免非数组数据调用map方法报错
- 下拉菜单的key值要保证唯一,避免重复key导致的渲染问题
- 如果数据量较大,可以考虑做简单的缓存,避免重复请求
- 请求过程中可以添加加载状态,提升用户体验