采用uniapp-vue3实现的数据选择器,支持H5、微信小程序(其他小程序未测试过,可自行尝试)
- 支持本地自定义过滤、远程接口过滤,
- 为了避免弹窗面板超出边界的情况,自动计算弹窗面板安置的位置(在微信小程序,节点信息是页面渲染后才拿得到,所以会有一段位移过程,大神如果更合适的方案,可以自行优化)
- 支持自定义弹窗面板显示内容
- 支持自定义取值字段(默认为options: [{label:‘键’, value: ‘值’, …}]格式)
由于移动端输入场景下会弹出键盘,如果设置为失焦时关闭弹窗面板, 则收起键盘时,弹窗就会被关闭,无法再进行下一步选择。所以采用弹窗常驻,手动点击右边图标关闭弹窗的方式
可到插件市场下载尝试: https://ext.dcloud.net.cn/plugin?id=17287
- 使用示例
H5示例
微信小程序示例
props属性
id
组件唯一标识
同个页面存在多个wo-select组件的情况,id为必填项,因为需要通过id去计算弹窗面板与输入框的位置,以便安置弹窗面板在合适的位置,避免超出边界
id: {type: String,default: 'inputId',reqiured: true
},
value
默认值(valueField字段指定的字段值)
value: {type: String || Number,default: null
},
options
结构化数据
options: {type: Array,default: () => []
},
placeholder
占位描述
placeholder: {type: String,default: '请选择数据'
},
labelField
选中后输入框显示的值的取值字段
labelField: {type: String,default: 'label'
},
如果 options = [{ name: '按钮1', id: 1}, { name: '按钮2', id: 2 }]; labelField = 'name'
则选中后,输入框中则显示name字段的值
valueField
选中值的取值字段
valueField: {type: String,default: 'value'
}
如果 options = [{ name: '按钮1', id: 1}, { name: '按钮2', id: 2 }]; valueField = 'id'
则选中值就是id字段的值
事件
@filter
过滤事件,支持本地过滤、远程过滤等
@on-change
选中后返回值,值为valueField配置的字段值
示例
<template><view class="content"><view class="card"><view class="title">默认样式</view><view><wo-selectclass="white-select":id="'inputOne'":options="state.data":label-field="'label'":value-field="'value'"@filter="onFilter"@on-change="onChangeStaff1"></wo-select></view><view class="title">选中值为:{{ state.res1 }}</view></view><view class="card"><view class="title">设置初始值</view><view><wo-selectclass="white-select":id="'inputTwo2'":value="'2'":options="state.data":label-field="'label'":value-field="'value'"@filter="onFilter"@on-change="onChangeStaff2"></wo-select></view><view class="title">选中值为:{{ state.res2 }}</view></view><view class="card"><view class="title">自定义面板</view><view><wo-selectclass="white-select"ref="selectorRef1":id="'inputTwo1'":options="state.data":label-field="'label'":value-field="'value'"@filter="onFilter"@on-change="onChangeStaff3"><view style="display: flex; flex-direction: column; gap: 20rpx"><view style="display: flex; justify-content:center">这是头部</view><viewv-for="item in state.data":key="item.value"style="font-size: 24rpx; z-index: 120; display: flex; justify-content: space-between;"@click="selectorRef1.onClickSelect(item)"><view style="width: 200px;">{{ item.label }}</view><view style="background-color: dodgerblue; color: white; padding: 4px 8px;border-radius: 8rpx;">{{ item.category }}</view></view></view></wo-select></view><view class="title">选中值为:{{ state.res3 }}</view></view><view class="card dark"><view class="title" style="color: white">暗黑样式</view><view><wo-selectclass="dark-select"ref="selectorRef":id="'inputTwo'":options="state.data":label-field="'label'":value-field="'value'"@filter="onFilter"@on-change="onChangeStaff4"><view style="display: flex; flex-direction: column; gap: 20rpx"><viewv-for="item in state.data":key="item.value"style="font-size: 24rpx; z-index: 120; display: flex; justify-content: space-between;"@click="selectorRef.onClickSelect(item)"><view style="width: 200px;">{{ item.label }}</view><view style="background-color: dodgerblue; color: white; padding: 4px 8px;border-radius: 8rpx;">{{ item.category }}</view></view></view></wo-select></view><view class="title" style="color: white;">选中值为:{{ state.res4 }}</view></view><view class="flex-center">内容区</view><view class="card"><view class="title">面板位置自动调整</view><view><wo-selectclass="white-select":id="'inputThree'":placeholder="'输入过滤'":options="state.data":label-field="'label'":value-field="'value'"@filter="onFilter"@on-change="onChangeStaff5"></wo-select></view><view class="title">选中值为:{{ state.res5 }}</view></view><view class="flex-center">内容区</view></view>
</template><script setup lang="ts">import { reactive, ref } from 'vue'const selectorRef1 = ref()const selectorRef = ref();const state = reactive({data: [{label: '哈墨的脑袋',value: '1',category: '正常'},{label: '摩西女神的手臂',value: '2',category: '异常'},{label: '奥尔墨的铠甲',value: '3',category: '维修中'},{label: '摩西女神的翅膀',value: '4',category: '正常'},{label: '战神瑞尔的斧头',value: '5',category: '正常'},{label: '丘比特的箭头',value: '6',category: '异常'},{label: '雅典娜的光明盾',value: '7',category: '异常'}] as any[],userOptions: [] as any[],res1: '',res2: '',res3: '',res4: '',res5: '',})// 克隆一份数据,用于过滤筛选state.userOptions = JSON.parse(JSON.stringify(state.data))const onFilter = (e: any) => {state.data = state.userOptions.filter((res) => {return res.label.indexOf(e.detail.value) !== -1});};const onChangeStaff1 = (e: any) => {state.res1 = e};const onChangeStaff2 = (e: any) => {state.res2 = e};const onChangeStaff3 = (e: any) => {state.res3 = e};const onChangeStaff4 = (e: any) => {state.res4 = e};const onChangeStaff5 = (e: any) => {state.res5 = e};
</script><style scoped>.content {width: 100%;font-size: 28rpx;}.card {padding: 20px;}.dark {background-color: black;}.dark-select {color: white;}.title {font-weight: 600;font-size: 24rpx;padding-bottom: 10rpx;}:deep .dark-select .panel {background-color: black;}.box {padding: 20px;}.flex-center {display: flex;justify-content: center;align-items: center;height: 600px;background: #666;}
</style>