在Uniapp开发微信小程序时,下拉选择器是高频使用的UI组件。原生picker组件虽然基础功能完善,但在实际业务中往往面临几个痛点:
这个自定义插槽下拉选择器组件正是为解决这些问题而生。通过封装uview-plus的picker组件,实现了:
提示:组件设计时特别考虑了与后端API的对接便利性,valueKey/showKey的配置可以让组件自动提取接口返回的任意字段作为展示值和实际值
组件通过类型判断实现自动适配不同格式的数据源:
javascript复制// 在updateSelectedText方法中的类型判断逻辑
const findItem = props.list.find(item => {
if (typeof item === 'string') return item === newVal; // 字符串数组处理
const itemValue = item[props.valueKey] + ''; // 对象数组处理
const targetValue = newVal + '';
return itemValue === targetValue;
});
这种设计带来两个实际优势:
回显功能由三个关键部分组成:
javascript复制watch(() => props.modelValue, (newVal) => {
nextTick(() => updateSelectedText(newVal));
}, { immediate: true });
javascript复制const calcPickerIndex = (targetValue) => {
const targetIndex = props.list.findIndex(item => {
// 类型判断逻辑...
});
pickerDefaultIndex.value = targetIndex > -1 ? targetIndex : 0;
};
javascript复制const simpleSelectedText = computed(() => {
return rawSelectedText.value || props.placeholder;
});
组件通过作用域插槽实现UI解耦:
html复制<slot :showText="simpleSelectedText" :openPicker="openSimplePicker">
<!-- 默认按钮实现 -->
<up-button type="info" @tap="openSimplePicker">
{{ simpleSelectedText }}
</up-button>
</slot>
这种设计模式让使用者可以:
html复制<GeneralPicker
:list="['北京','上海','广州']"
v-model="selectedCity"
/>
html复制<GeneralPicker
:list="[
{ id: 1, name: '管理员' },
{ id: 2, name: '编辑' }
]"
showKey="name"
valueKey="id"
v-model="selectedRoleId"
/>
html复制<GeneralPicker :list="options" v-model="value">
<template #default="{ showText, openPicker }">
<view class="custom-trigger" @click="openPicker">
<text>{{ showText }}</text>
<u-icon name="arrow-down"></u-icon>
</view>
</template>
</GeneralPicker>
javascript复制// 从接口获取数据后直接赋值
const loadData = async () => {
const res = await api.getOptions();
options.value = res.data; // 组件会自动处理数据变化
}
通过CSS变量修改选择器样式:
css复制:root {
--up-picker-title-font-size: 16px;
--up-picker-toolbar-height: 50px;
--up-picker-option-font-size: 14px;
}
当选项超过100条时建议:
优化后的数据加载示例:
javascript复制const loadMore = () => {
if (loading.value) return;
loading.value = true;
api.getPagedOptions(page.value).then(res => {
options.value = [...options.value, ...res.data];
page.value++;
}).finally(() => {
loading.value = false;
});
}
通过修改columns配置可实现多级联动:
javascript复制const columns = ref([
[{text:'A'}, {text:'B'}],
[{text:'A1'}, {text:'B1'}]
]);
<up-picker :columns="columns" />
扩展组件添加搜索框:
html复制<template>
<view>
<u-search v-model="keyword" @search="filterOptions" />
<GeneralPicker :list="filteredList" />
</view>
</template>
为Props添加TypeScript类型定义:
typescript复制interface PickerProps {
list: Array<string | Record<string, any>>;
title?: string;
valueKey?: string;
showKey?: string;
modelValue?: string | number;
}
const props = defineProps<PickerProps>();
在实际项目中使用这个组件后,表单页面的开发效率提升了约40%,特别是对于复杂数据结构的处理不再需要编写重复的转换代码。一个典型的省市区三级联动选择器,原本需要200+行的逻辑现在只需要50行左右即可实现。