Select 选择器
当选项过多时,使用下拉菜单展示并选择内容,支持搜索过滤和远程加载。
基础用法
适用广泛的基础单选 v-model 的值为当前被选中的 option 的 value 属性值。
<script setup>
import { ref } from 'vue'
import Select from '@/components/Select/Select.vue'
const test = ref('')
const options2 = [
{ label: 'hello', value: '1' },
{ label: 'xyz', value: '2' },
{ label: 'testing', value: '3' },
{ label: 'check', value: '4', disabled: true }
]
</script>
<template>
<Select v-model="test" placeholder="基础选择器,请选择" :options="options2" clearable filterable multiple collapseTags/>
<span>{{test}}</span>
</template>自定义选项渲染
通过 renderLabel 属性传入渲染函数,可以自定义选项内容的展示样式,使用 VNode 灵活渲染。
<script setup>
import { h, ref } from 'vue'
import Select from "@/components/Select/Select.vue"
const test = ref('')
const options2 = [
{label: 'hello', value: '1'},
{label: 'xyz', value: '2'},
{label: 'testing', value: '3'},
{label: 'check', value: '4', disabled: true},
]
const customRender = (option) => {
return h('div', { className: 'xyz' }, [h('b', option.label), h('span', option.value)])
}
</script>
<template>
<Select v-model="test" placeholder="基础选择器,请选择" :options="options2" :renderLabel="customRender"></Select>
</template>
<style>
.vk-select__menu-item, .xyz {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
</style>远程搜索
当需要从服务器加载数据时,可使用远程搜索功能。通过输入关键字触发搜索,动态加载选项数据。
当前选择:
<template>
<div>
<Select
v-model="selected"
:options="options"
placeholder="请输入关键词搜索"
filterable
remote
:remote-method="handleFetch"
clearable
/>
<p>当前选择: {{ selected }}</p>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import Select from '../../../src/components/Select/Select.vue';
import type { SelectOption } from '../../../src/components/Select/types';
const selected = ref('');
const options = ref<SelectOption[]>([]);
// 模拟远程数据
const remoteData = [
{ label: '北京', value: 'beijing' },
{ label: '上海', value: 'shanghai' },
{ label: '广州', value: 'guangzhou' },
{ label: '深圳', value: 'shenzhen' },
{ label: '杭州', value: 'hangzhou' },
{ label: '南京', value: 'nanjing' },
{ label: '成都', value: 'chengdu' },
{ label: '武汉', value: 'wuhan' },
{ label: '西安', value: 'xian' },
{ label: '重庆', value: 'chongqing' },
{ label: '天津', value: 'tianjin' },
{ label: '苏州', value: 'suzhou' },
{ label: '厦门', value: 'xiamen' },
{ label: '青岛', value: 'qingdao' },
{ label: '大连', value: 'dalian' },
{ label: '长沙', value: 'changsha' },
{ label: '郑州', value: 'zhengzhou' },
{ label: '昆明', value: 'kunming' },
{ label: '济南', value: 'jinan' },
{ label: '合肥', value: 'hefei' },
{ label: '福州', value: 'fuzhou' },
{ label: '沈阳', value: 'shenyang' },
{ label: '长春', value: 'changchun' },
{ label: '贵阳', value: 'guiyang' },
{ label: '南宁', value: 'nanning' },
{ label: '哈尔滨', value: 'harbin' },
{ label: '太原', value: 'taiyuan' },
{ label: '石家庄', value: 'shijiazhuang' },
{ label: '乌鲁木齐', value: 'wulumuqi' },
{ label: '拉萨', value: 'lasa' },
{ label: '南昌', value: 'nanchang' },
{ label: '海口', value: 'haikou' },
{ label: '兰州', value: 'lanzhou' },
{ label: '银川', value: 'yinchuan' },
{ label: '西宁', value: 'xining' },
{ label: '呼和浩特', value: 'huhehaote' },
{ label: '台北', value: 'taipei' },
{ label: '香港', value: 'hongkong' },
{ label: '澳门', value: 'macau' },
{ label: '宁波', value: 'ningbo' },
{ label: '温州', value: 'wenzhou' },
{ label: '无锡', value: 'wuxi' },
{ label: '常州', value: 'changzhou' },
{ label: '东莞', value: 'dongguan' },
{ label: '佛山', value: 'foshan' },
];
// 模拟远程搜索方法
const remoteMethod = (query: string): Promise<SelectOption[]> => {
return new Promise((resolve) => {
if (query.trim() === '') {
resolve([]);
return;
}
// 模拟网络请求延迟
setTimeout(() => {
const results = remoteData.filter(item =>
item.label.toLowerCase().includes(query.toLowerCase())
);
resolve(results);
}, 800);
});
};
const handleFetch = (query) => {
if(!query) return Promise.resolve([])
return fetch(`https://api.github.com/search/repositories?q=${query}`)
.then(res => res.json())
.then(({items}) => {
return items.slice(0, 10).map(item => ({ label: item.name, value: item.node_id }))
})
}
</script>Attributes
| 名称 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| model-value / v-model | 绑定值 | string | string[] | — |
| options | 下拉选项数组 | SelectOption[] | [] |
| placeholder | 占位文本 | string | 请选择 |
| disabled | 是否禁用 | boolean | false |
| clearable | 是否显示清空按钮 | boolean | false |
| filterable | 是否可搜索 | boolean | false |
| filterMethod | 自定义搜索方法 | (value: string) => SelectOption[] | — |
| remote | 是否开启远程搜索 | boolean | false |
| remoteMethod | 远程搜索方法 | (value: string) => Promise<SelectOption[]> | — |
| renderLabel | 自定义选项渲染函数 | (option: SelectOption) => VNode | — |
| multiple | 是否多选 | boolean | false |
| collapseTags | 多选时是否折叠显示已选标签 | boolean | false |
SelectOption
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| label | 选项标签文本 | string | — |
| value | 选项的值 | string | — |
| disabled | 是否禁用 | boolean | false |
Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| update:modelValue | 值更新时触发 | (value: string | string[]) |
| change | 选中值变化时触发 | (value: string | string[]) |
| visible-change | 下拉框显示/隐藏时触发 | (visible: boolean) |
| clear | 点击清空按钮时触发 | — |
| remove-tag | 多选模式下移除标签时触发 | (value: string) |