介绍
组合了列表选择弹出框、输入框组件,实现了便捷快速的选择功能。
引入
js
import SelectInput from 'sard-uniapp/components/select-input/select-input.vue'代码演示
基础使用
使用 v-model 绑定当前值,通过 title 和 placeholder 属性设置弹出框标题和输入框占位文本。
在点击输入框后会显示列表选择弹出框。
相比较于 Select 和 SelectPopout 组件,SelectInput 组件需要传递 options 属性,因为需要通过此属性获取当前值对应的标签,以便显示在输入框内。
vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
:options="regionData"
:option-keys="{ label: 'name', value: 'code', children: '' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:440000 (广东省)"
arrow
hover
@click="value = 440000"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getRegionData } from 'region-data'
const regionData = getRegionData()
const value = ref<number>()
const onChange = (value: any) => {
console.log('change', value)
}
</script>vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
:options="regionData"
:option-keys="{ label: 'name', value: 'code', children: '' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:440000 (广东省)"
arrow
hover
@click="value = 440000"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
import { getRegionData } from "region-data";
const regionData = getRegionData();
const value = ref();
const onChange = (value2) => {
console.log("change", value2);
};
</script>自定义插槽
SelectInput 组件依然可以像 Select 和 SelectPopout 组件一样使用插槽自定义内容。
但 options 属性还是必传的。
vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
:options="colors"
@change="onChange"
>
<view class="grid grid-cols-2 gap-16 px-32">
<sar-select-option
v-for="item in colors"
:key="item.value"
:value="item.value"
plain
>
<template #default="{ selected }">
<view
class="box-border flex-1 flex p-16 border border-base border-solid gap-16 rounded"
:class="{ 'border-primary': selected }"
style="width: calc((100vw - 32rpx * 2 - 16rpx) / 2)"
>
<view
class="size-48 rounded-sm"
:style="{ background: item.value }"
></view>
<view>{{ item.label }}</view>
</view>
</template>
</sar-select-option>
</view>
</sar-select-input>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:#FFDE0A (yellow)"
arrow
hover
@click="value = '#FFDE0A'"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const colors = [
{
value: '#E63415',
label: 'red',
},
{
value: '#FF6600',
label: 'orange',
},
{
value: '#FFDE0A',
label: 'yellow',
},
{
value: '#1EC79D',
label: 'green',
},
{
value: '#14CCCC',
label: 'cyan',
},
{
value: '#4167F0',
label: 'blue',
},
]
const value = ref<string>()
const onChange = (value: any) => {
console.log('change', value)
}
</script>vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
:options="colors"
@change="onChange"
>
<view class="grid grid-cols-2 gap-16 px-32">
<sar-select-option
v-for="item in colors"
:key="item.value"
:value="item.value"
plain
>
<template #default="{ selected }">
<view
class="box-border flex-1 flex p-16 border border-base border-solid gap-16 rounded"
:class="{ 'border-primary': selected }"
style="width: calc((100vw - 32rpx * 2 - 16rpx) / 2)"
>
<view
class="size-48 rounded-sm"
:style="{ background: item.value }"
></view>
<view>{{ item.label }}</view>
</view>
</template>
</sar-select-option>
</view>
</sar-select-input>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:#FFDE0A (yellow)"
arrow
hover
@click="value = '#FFDE0A'"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const colors = [
{
value: "#E63415",
label: "red"
},
{
value: "#FF6600",
label: "orange"
},
{
value: "#FFDE0A",
label: "yellow"
},
{
value: "#1EC79D",
label: "green"
},
{
value: "#14CCCC",
label: "cyan"
},
{
value: "#4167F0",
label: "blue"
}
];
const value = ref();
const onChange = (value2) => {
console.log("change", value2);
};
</script>多选
默认选择的选项的标签最多 10 会显示在输入框,其余通过 +<rest> 的形式展示。可以通过 max-labels 属性设置最多展示的标签数。
vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
multiple
show-toolbar
:max-labels="3"
:options="regionData"
:option-keys="{ label: 'name', value: 'code', children: '' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:[440000, 450000] (广东省,广西)"
arrow
hover
@click="value = [440000, 450000]"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { getRegionData } from 'region-data'
const regionData = getRegionData()
const value = ref<number[]>()
const onChange = (value: any) => {
console.log('change', value)
}
</script>vue
<template>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
title="请选择"
placeholder="请选择"
clearable
multiple
show-toolbar
:max-labels="3"
:options="regionData"
:option-keys="{ label: 'name', value: 'code', children: '' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item
title="设置为:[440000, 450000] (广东省,广西)"
arrow
hover
@click="value = [440000, 450000]"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
import { getRegionData } from "region-data";
const regionData = getRegionData();
const value = ref();
const onChange = (value2) => {
console.log("change", value2);
};
</script>远程
远程的使用参考 SelectPopout ,不多赘述。
当远程数据没有加载时,输入框会显示对应的 value 值。值的已加载的标签会被缓存起来,后续筛选清空列表时也能显示缓存的标签。
vue
<template>
<view>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
v-model:visible="visible"
title="请选择"
placeholder="请选择"
filterable
filter-placeholder="请输入过滤关键词"
remote
:remote-method="remoteMethod"
:options="listData"
:option-keys="{ label: 'name', value: 'code' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item arrow hover @click="visible = true">
<template #title>
{{ value ? JSON.stringify(value) : '请选择' }}
</template>
</sar-list-item>
<sar-list-item
title="设置为:440100 (广州市)"
arrow
hover
@click="value = 440100"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { mapCities } from 'region-data'
import { sleep } from 'sard-uniapp'
const visible = ref(false)
const value = ref<number>()
const onChange = (value: any) => {
console.log('change', value)
}
// server
const cities = Object.entries(mapCities).map(([code, name]) => ({
code: +code,
name,
}))
const mockRequest = async (query: string, page = 1, pageSize = 10) => {
await sleep(300)
const filteredData = query
? cities.filter((item) => item.name.includes(query))
: cities
const offset = (page - 1) * pageSize
return {
list: filteredData.slice(offset, offset + pageSize),
total: filteredData.length,
}
}
// client
const listData = ref<
{
code: number
name: string
}[]
>([])
const remoteMethod = async (
query: string,
page: number,
isRefresh: boolean,
) => {
return mockRequest(query, page).then(({ list = [], total = 0 }) => {
if (isRefresh) {
listData.value = [...list]
} else {
listData.value = [...listData.value, ...list]
}
return listData.value.length >= total || list.length === 0
})
}
</script>vue
<template>
<view>
<sar-list card>
<sar-list-item>
<sar-select-input
v-model="value"
v-model:visible="visible"
title="请选择"
placeholder="请选择"
filterable
filter-placeholder="请输入过滤关键词"
remote
:remote-method="remoteMethod"
:options="listData"
:option-keys="{ label: 'name', value: 'code' }"
@change="onChange"
/>
</sar-list-item>
<sar-list-item arrow hover @click="visible = true">
<template #title>
{{ value ? JSON.stringify(value) : '请选择' }}
</template>
</sar-list-item>
<sar-list-item
title="设置为:440100 (广州市)"
arrow
hover
@click="value = 440100"
/>
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</view>
</template>
<script setup lang="js">
import { ref } from "vue";
import { mapCities } from "region-data";
import { sleep } from "sard-uniapp";
const visible = ref(false);
const value = ref();
const onChange = (value2) => {
console.log("change", value2);
};
const cities = Object.entries(mapCities).map(([code, name]) => ({
code: +code,
name
}));
const mockRequest = async (query, page = 1, pageSize = 10) => {
await sleep(300);
const filteredData = query ? cities.filter((item) => item.name.includes(query)) : cities;
const offset = (page - 1) * pageSize;
return {
list: filteredData.slice(offset, offset + pageSize),
total: filteredData.length
};
};
const listData = ref([]);
const remoteMethod = async (query, page, isRefresh) => {
return mockRequest(query, page).then(({ list = [], total = 0 }) => {
if (isRefresh) {
listData.value = [...list];
} else {
listData.value = [...listData.value, ...list];
}
return listData.value.length >= total || list.length === 0;
});
};
</script>API
SelectInputProps
继承 SelectPopoutProps 并有以下额外属性:
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| max-labels | 多选时,输入框最大展示标签个数,设为 -1 表示不限制 | number | 10 |
SelectInputSlots
继承 SelectPopoutSlots和PopoutInputSlots