基于 UniApp 的弹出层选择器单选、多选组件,支持单选、多选、搜索、数量输入等功能。专为移动端优化,提供丰富的交互体验。

yu-select 选择器组件

基于 UniApp 的弹出层选择器单选、多选组件,支持单选、多选、搜索、数量输入等功能。专为移动端优化,提供丰富的交互体验。

效果

地址

插件市场

gitee

功能特性

  • 多种选择模式:支持单选(radio)和多选(checkbox)模式
  • 智能搜索:内置搜索功能,支持实时过滤,大小写不敏感
  • 数量管理:支持数量输入框,可设置选项数量
  • 默认值设置:支持单选和多选的默认值预设
  • 下拉加载:支持滚动到底部加载更多数据
  • 全选功能:多选模式下支持一键全选/全不选
  • 交互优化:支持点击选中/取消,数量输入自动选中
  • 视觉反馈:选中状态高亮显示,已选标签展示
  • 多端适配:响应式设计,完美支持H5、小程序、App
  • 清空功能:支持一键清空所有选择和数量
  • 防误触:弹窗滚动不影响背景页面

安装使用

  1. uni_modules/yu-select 目录复制到您的 UniApp 项目的 uni_modules 目录下
  2. 在页面中引入组件:
vue 复制代码
<template>
  <yu-select 
    :show="showSelect" 
    :dataLists="dataList" 
    @cancel="showSelect = false" 
    @submit="handleSelectSubmit"
  />
</template>

<script setup>
import { ref } from 'vue';

const showSelect = ref(false);
const dataList = ref([
  { label: '选项1', value: 1 },
  { label: '选项2', value: 2 },
  // ...
]);

function handleSelectSubmit(selectedData) {
  console.log('选中的数据:', selectedData);
}
</script>

Props 属性

属性名 类型 默认值 说明 备注
dataLists Array [] 数据列表 对象数组,每个对象需包含nameKey和valueKey字段
nameKey String 'label' 显示名称的字段名 用于列表项显示的文本字段
valueKey String 'value' 值字段名 用作唯一标识的字段
numKey String 'num' 数量字段名 showNum为true时使用的数量字段
show Boolean false 是否显示弹窗 控制组件的显示隐藏
type String 'radio' 选择类型 'radio'单选 / 'checkbox'多选
showSearch Boolean true 是否显示搜索框 开启后可实时搜索过滤数据
showNum Boolean false 是否显示数量输入框 开启后每个选项可输入数量
popupTitle String '列表选择' 弹窗标题 显示在弹窗顶部的标题文字
placeholder String '请输入搜索内容' 搜索框占位符 搜索输入框的提示文字
isClearable Boolean false 是否可清空 设为true时会清空所有选择和数量
defaultValue String/Number/Array null 默认选中值 单选传值,多选传数组

Events 事件

事件名 参数 说明 触发时机
search keyword 搜索事件,返回搜索关键词 用户输入搜索内容时实时触发
lower - 滚动到底部事件,用于加载更多 列表滚动到底部时触发
cancel - 取消选择事件 点击取消按钮或遮罩层时触发
submit selectedData 提交选择事件,返回选中的数据 点击确认按钮时触发

使用示例

基本单选示例

vue 复制代码
<yu-select 
  :show="showSelect" 
  :dataLists="listData" 
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

多选带数量示例

vue 复制代码
<yu-select 
  :show="showSelect" 
  type="checkbox" 
  :showNum="true" 
  :dataLists="listData" 
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

设置默认值

vue 复制代码
<!-- 单选默认值 -->
<yu-select 
  :show="showSelect" 
  :defaultValue="1" 
  :dataLists="listData" 
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

<!-- 多选默认值 -->
<yu-select 
  :show="showSelect" 
  type="checkbox"
  :defaultValue="[1, 2]" 
  :dataLists="listData" 
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

带搜索和下拉加载

vue 复制代码
<yu-select 
  :show="showSelect" 
  :dataLists="listData" 
  placeholder="输入工站名称搜索"
  @cancel="showSelect = false" 
  @submit="handleSubmit"
  @search="handleSearch"
  @lower="loadMore"
/>

<script setup>
function handleSearch(keyword) {
  console.log('搜索关键词:', keyword);
  // 处理搜索逻辑
}

function loadMore() {
  console.log('加载更多数据');
  // 处理分页加载
}
</script>

清空功能

vue 复制代码
<yu-select 
  :show="showSelect" 
  :isClearable="needClear"
  :dataLists="listData" 
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

<script setup>
const needClear = ref(false);

// 触发清空
function clearSelection() {
  needClear.value = true;
  nextTick(() => {
    needClear.value = false;
  });
}
</script>

自定义字段名

vue 复制代码
<yu-select 
  :show="showSelect" 
  :dataLists="customData" 
  nameKey="cworkStationName"
  valueKey="id"
  numKey="quantity"
  :showNum="true"
  @cancel="showSelect = false" 
  @submit="handleSubmit"
/>

<script setup>
const customData = ref([
  { id: 1, cworkStationName: '工作站A', quantity: 0 },
  { id: 2, cworkStationName: '工作站B', quantity: 0 }
]);
</script>

数据格式

组件期望的数据格式为对象数组,每个对象至少包含 nameKeyvalueKey 对应的字段:

标准格式

javascript 复制代码
const dataList = [
  { label: '选项1', value: 1, num: 0 },
  { label: '选项2', value: 2, num: 0 },
  { label: '选项3', value: 3, num: 0 }
];

自定义字段格式

javascript 复制代码
const customDataList = [
  { id: 1, cworkStationName: '工作站A', quantity: 0 },
  { id: 2, cworkStationName: '工作站B', quantity: 5 },
  { id: 3, cworkStationName: '工作站C', quantity: 3 }
];

// 对应的组件配置
// nameKey="cworkStationName" valueKey="id" numKey="quantity"

字段说明

  • nameKey字段:必需,用于显示的文本内容
  • valueKey字段:必需,用作唯一标识,支持字符串或数字
  • numKey字段:可选,当showNum为true时使用,存储数量值

返回值格式

组件通过 submit 事件返回选中的数据,格式如下:

单选模式 (type="radio")

返回单个选中的对象,如果未选中则返回空对象:

javascript 复制代码
// 有选中项
{ label: '选项1', value: 1, num: 5 }

// 未选中
{}

多选模式 (type="checkbox")

返回选中的对象数组:

javascript 复制代码
// 选中多项
[
  { label: '选项1', value: 1, num: 5 },
  { label: '选项2', value: 2, num: 3 }
]

// 未选中任何项
[]

处理返回数据

javascript 复制代码
function handleSubmit(selectedData) {
  if (type === 'radio') {
    if (selectedData && selectedData.value) {
      console.log('选中的值:', selectedData.value);
      console.log('选中的文本:', selectedData.label);
      console.log('输入的数量:', selectedData.num);
    } else {
      console.log('未选中任何项');
    }
  } else {
    console.log('选中的项数:', selectedData.length);
    selectedData.forEach(item => {
      console.log(`${item.label}: ${item.num || 0}`);
    });
  }
}

样式定制

组件使用 SCSS 编写样式,提供完整的主题色配置:

主题变量

scss 复制代码
// 主题色配置
$primary-color: #2B8BE4;        // 主题色
$primary-light: #EBF5FD;        // 浅色背景
$primary-text: #0076F9;         // 主要文字色

自定义主题

可以通过覆盖这些变量来自定义样式:

scss 复制代码
// 在你的全局样式文件中
$primary-color: #007AFF;        // 自定义主题色
$primary-light: #E3F2FD;        // 自定义浅色背景
$primary-text: #1976D2;         // 自定义文字色

@import '@/uni_modules/yu-select/components/yu-select/yu-select.vue';

关键样式类

  • .popup-mask: 遮罩层样式
  • .popup-content: 弹窗内容区域
  • .search-box: 搜索框样式
  • .select-row: 列表行样式
  • .custom-radio-icon / .custom-checkbox-icon: 选择图标样式
  • .bottons: 底部按钮区域样式

浏览器兼容性

  • ✅ H5
  • ✅ 微信小程序
  • ✅ App
  • ✅ 其他小程序平台

高级用法

交互行为优化

组件提供了多种智能交互:

  1. 点击切换选择:点击已选中项可取消选择
  2. 数量输入联动
    • 输入数量大于0自动选中该项
    • 清空数量或输入0自动取消选择
  3. 搜索实时过滤:输入关键词实时过滤列表
  4. 全选功能:多选模式下支持一键全选/取消全选

性能优化

javascript 复制代码
// 大量数据时建议使用分页加载
function loadMore() {
  if (loading || !hasMore) return;
  loading = true;
  
  // 模拟接口请求
  setTimeout(() => {
    const newData = generateData(currentPage + 1);
    dataLists.value.push(...newData);
    currentPage++;
    loading = false;
  }, 500);
}

状态管理

javascript 复制代码
// 使用组合式API管理选择状态
const { selectedData, showSelect, handleSubmit } = useSelect();

function useSelect() {
  const selectedData = ref([]);
  const showSelect = ref(false);
  
  function handleSubmit(data) {
    selectedData.value = data;
    showSelect.value = false;
    // 处理业务逻辑
  }
  
  return {
    selectedData,
    showSelect,
    handleSubmit
  };
}

注意事项

  1. 滚动穿透防护 :组件使用了 touchmove.stop.prevent 来防止弹窗内滚动影响外部页面
  2. 数量输入限制 :数量输入框仅在 showNum="true" 时显示,支持数字类型输入
  3. 搜索功能 :搜索功能默认开启,可通过 showSearch="false" 关闭,搜索不区分大小写
  4. 多端适配:组件会自动处理各端的样式差异,特别是安全区域适配
  5. 数据响应式:dataLists 变化时组件会自动更新,支持动态数据源
  6. 内存管理:大量数据时建议使用虚拟滚动或分页加载避免性能问题
  7. 字段映射:确保 dataLists 中的对象包含正确的 nameKey 和 valueKey 字段
  8. 默认值设置:defaultValue 仅在组件初始化时生效,后续变化需要手动处理

更新日志

v1.1.0 (2025-09-24)

功能增强

  • ✨ 新增点击选中项可取消选择的交互优化
  • ✨ 新增数量输入与选择状态的智能联动
  • ✨ 优化搜索功能,支持大小写不敏感搜索
  • ✨ 新增已选标签展示功能(多选模式)
  • ✨ 改进全选/全不选的用户体验
  • ✨ 新增清空搜索按钮,提升操作便利性
  • 🐛 修复数量输入框在不同选择状态下的显示问题
  • 🐛 修复默认值设置在某些情况下不生效的问题
  • 💄 优化UI细节,提升视觉体验
  • 📝 完善组件注释和文档

技术改进

  • 🔧 优化数据初始化和更新逻辑
  • 🔧 改进组件内部状态管理
  • 🔧 增强多端兼容性处理
  • ⚡ 提升搜索性能和响应速度

v1.0.0 (2025-09-23)

初始版本发布

  • ✅ 支持单选/多选模式
  • ✅ 支持搜索功能
  • ✅ 支持数量输入
  • ✅ 支持默认值设置
  • ✅ 支持下拉加载更多
  • ✅ 基础UI和交互实现

常见问题

Q: 如何实现异步数据加载?

A: 使用 @lower 事件监听滚动到底部,在回调中加载更多数据:

javascript 复制代码
function loadMore() {
  if (!hasMore || loading) return;
  // 异步加载数据并追加到 dataLists
}

Q: 如何自定义选择图标样式?

A: 可以通过覆盖 .custom-radio-icon.custom-checkbox-icon 类来自定义:

scss 复制代码
.custom-radio-icon .circle.checked {
  background: your-color;
  border-color: your-color;
}

Q: 搜索功能支持哪些匹配规则?

A: 目前支持模糊匹配,匹配 nameKey 字段内容,不区分大小写。

Q: 如何处理大量数据的性能问题?

A: 建议使用分页加载或虚拟滚动,避免一次性渲染过多DOM元素。

Q: 组件支持哪些平台?

A: 支持 H5、微信小程序、App 等 UniApp 支持的所有平台。

技术支持

如果您在使用过程中遇到问题,可以通过以下方式获取帮助:

  1. 查看本文档的常见问题部分
  2. 检查控制台是否有错误信息
  3. 确认数据格式是否正确
  4. 验证组件属性配置是否有误

作者

Yu - 专注于移动端组件开发

许可证

MIT License


💡 提示:建议在使用前先查看示例代码,了解组件的基本用法和配置方式。如需更复杂的功能,可以基于组件进行二次开发。

相关推荐
Qrun13 小时前
Windows11安装nvm管理node多版本
前端·vscode·react.js·ajax·npm·html5
中国lanwp13 小时前
全局 npm config 与多环境配置
前端·npm·node.js
JELEE.14 小时前
Django登录注册完整代码(图片、邮箱验证、加密)
前端·javascript·后端·python·django·bootstrap·jquery
TeleostNaCl16 小时前
解决 Chrome 无法访问网页但无痕模式下可以访问该网页 的问题
前端·网络·chrome·windows·经验分享
前端大卫18 小时前
为什么 React 中的 key 不能用索引?
前端
你的人类朋友18 小时前
【Node】手动归还主线程控制权:解决 Node.js 阻塞的一个思路
前端·后端·node.js
小李小李不讲道理20 小时前
「Ant Design 组件库探索」五:Tabs组件
前端·react.js·ant design
毕设十刻20 小时前
基于Vue的学分预警系统98k51(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
2501_9159090620 小时前
WebView 调试工具全解析,解决“看不见的移动端问题”
android·ios·小程序·https·uni-app·iphone·webview
mapbar_front21 小时前
在职场生存中如何做个不好惹的人
前端