# uni-combox

默认是单选选择框,通过 input 具名插槽切换为可输入、可选择的组合框。

本 Component 是 uni ext component,需下载插件:uni-combox

已废弃: uni-combox-x 仅用于兼容已有项目。新项目请安装并使用 uni-combobox。

uni-combox 组合框组件。

默认为单选模式,类似 select 组件,只能选择不能输入。通过具名插槽 input 传入 input 组件后,切换为可输入、可选择的组合模式。

# 基本用法

<uni-combox :options="options" placeholder="请选择" v-model="value" />

# options

<uni-combox :options="gradeOptions" placeholder="请选择年级" v-model="grade" />

# modelValue / v-model

<uni-combox :options="cityOptions" v-model="city" placeholder="请选择城市" />

# placeholder

<uni-combox :options="cityOptions" placeholder="这里展示 placeholder" v-model="value" />

# disabled

<uni-combox :options="cityOptions" v-model="city" disabled />

禁用后不可输入、展开或选择候选项。

# 组合模式

<uni-combox :options="options" v-model="city">
  <template #input="{ value, input, disabled }">
    <input
      :value="value"
      :disabled="disabled"
      placeholder="选择或输入城市"
      @input="input"
    />
  </template>
</uni-combox>

输入时会打开候选浮层,并按 startsWith 规则过滤候选项。点击右侧箭头打开时展示完整候选列表,并高亮当前输入匹配项。

# 自定义样式

<uni-combox
  :options="options"
  v-model="value"
  arrow-class="demo-arrow"
  field-class="demo-field"
  options-view-class="demo-options-view"
  options-content-class="demo-options-content"
  option-text-class="demo-option-text"
  option-text-highlight-class="demo-option-highlight"
  option-row-highlight-class="demo-option-row-highlight"
  result-text-class="demo-result-text"
/>

也可以单独传入任意一个样式类属性。

<uni-combox :options="options" v-model="value" arrow-class="demo-arrow" />
<uni-combox :options="options" v-model="value" options-view-class="demo-options-view" />
<uni-combox :options="options" v-model="value" option-text-class="demo-option-text" />
<uni-combox :options="options" v-model="value" option-text-highlight-class="demo-option-highlight" />
<uni-combox :options="options" v-model="value" option-row-highlight-class="demo-option-row-highlight" />
<uni-combox :options="options" v-model="value" result-text-class="demo-result-text" />

# 事件

<uni-combox
  :options="options"
  v-model="value"
  @update:modelValue="onUpdateModelValue"
  @selectchange="onSelectChange"
/>

# 浮层

候选浮层通过 teleport 渲染到页面层,不受组件自身尺寸裁剪。下方空间不足且上方空间更充足时,会自动向上展开。默认最大高度为 200px。

候选浮层内部使用 scroll-view。

# External Classes

类名 说明
arrow-class 右侧箭头样式
field-class 非弹出区域样式
options-view-class 候选浮层外层样式
options-content-class 候选浮层内容样式
option-text-class 候选项文字样式
option-text-highlight-class 候选项高亮样式
option-row-highlight-class 候选项高亮行样式
result-text-class 单选模式结果文字样式

# Props

属性名 类型 默认值 说明
options Array<String> [] 候选字符串数组
modelValue String '' 当前值,支持 v-model
placeholder String '' 占位文字
disabled Boolean false 是否禁用
arrowClass String '' 右侧箭头自定义样式类
fieldClass String '' 非弹出区域自定义样式类
optionsViewClass String '' 候选浮层外层自定义样式类
optionsContentClass String '' 候选浮层内容自定义样式类
optionTextClass String '' 候选项文字自定义样式类
optionTextHighlightClass String '' 候选项高亮自定义样式类
optionRowHighlightClass String '' 候选项高亮行自定义样式类
resultTextClass String '' 单选模式结果文字自定义样式类

# Events

事件名 说明 回调参数
update:modelValue 值更新时触发 value: string
selectchange 从候选项选中时触发 value: string

# Expose

方法名 说明
setInputValue(value: string) 设置当前值并打开过滤候选
openOptions() 打开候选浮层
closeOptions() 关闭候选浮层

# 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS(VDOM) iOS(Vapor) HarmonyOS(VDOM) HarmonyOS(Vapor)
5.31 5.31 5.31 5.31 x 5.31 x 5.31

# 属性

名称 类型 描述
options string[] 候选字符串数组
modelValue string 当前值,支持 v-model 双向绑定
placeholder string 占位文字
disabled boolean 是否禁用
arrowClass string(string.ClassString) 右侧箭头自定义样式类
fieldClass string(string.ClassString) 非弹出区域自定义样式类
optionsViewClass string(string.ClassString) 候选浮层外层自定义样式类
optionsContentClass string(string.ClassString) 候选浮层内容自定义样式类
optionTextClass string(string.ClassString) 候选项文字自定义样式类
optionTextHighlightClass string(string.ClassString) 候选项高亮自定义样式类
optionRowHighlightClass string(string.ClassString) 候选项高亮行自定义样式类
resultTextClass string(string.ClassString) 单选模式结果文字自定义样式类
@selectchange Function 从候选项选中时触发,参数为选中的值,类型为 string
@update:modelValue Event 值更新时触发,参数为当前值,类型为 string

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
	<scroll-view class="page">
		<view class="section">
			<text class="page-title">uni-combox 组合框</text>
			<text class="page-desc">默认单选模式只能从候选项中选择;传入 input 插槽后,可输入并按左侧匹配过滤候选项。</text>
		</view>

		<view class="section">
			<text class="group-title">属性示例</text>
		</view>

		<view class="section">
			<text class="section-title">options:候选字符串数组</text>
			<uni-combox
				:options="gradeOptions"
				placeholder="请选择年级"
				v-model="optionsValue"
			/>
			<text class="result-text">当前选择:{{ optionsValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">input 插槽:可输入可选择</text>
			<uni-combox
				:options="cityOptions"
				v-model="city"
				placeholder="选择或输入城市"
				@selectchange="onCityChange"
			>
				<template #input="{ value, input, focus, disabled }">
					<input
						class="custom-input"
						:value="value"
						:disabled="disabled"
						placeholder="选择或输入城市"
						@focus="focus"
						@input="input"
					/>
				</template>
			</uni-combox>
			<text class="result-text">当前输入:{{ city }}</text>
		</view>

		<view class="section">
			<text class="section-title">placeholder:占位文字</text>
			<uni-combox
				:options="cityOptions"
				placeholder="这里展示 placeholder"
				v-model="placeholderValue"
			/>
			<text class="result-text">未选择时展示占位文字</text>
		</view>

		<view class="section">
			<text class="section-title">disabled:禁用状态</text>
			<uni-combox
				:options="gradeOptions"
				v-model="disabledValue"
				disabled
			/>
			<text class="result-text">禁用时不可展开或修改:{{ disabledValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">arrow-class:右侧箭头样式</text>
			<uni-combox
				:options="statusOptions"
				placeholder="请选择状态"
				v-model="arrowClassValue"
				arrow-class="demo-arrow"
			/>
			<text class="result-text">当前选择:{{ arrowClassValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">options-view-class:候选浮层样式</text>
			<uni-combox
				:options="cityOptions"
				placeholder="打开查看浮层样式"
				v-model="optionsViewClassValue"
				options-view-class="demo-options-view"
			/>
			<text class="result-text">当前选择:{{ optionsViewClassValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">option-text-class:候选项文字样式</text>
			<uni-combox
				:options="statusOptions"
				placeholder="打开查看候选文字"
				v-model="optionTextClassValue"
				option-text-class="demo-option-text"
			/>
			<text class="result-text">当前选择:{{ optionTextClassValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">option-text-highlight-class:高亮项文字样式</text>
			<uni-combox
				:options="cityOptions"
				v-model="optionTextHighlightClassValue"
				option-text-highlight-class="demo-option-highlight"
			/>
			<text class="result-text">打开后当前匹配项会使用高亮文字样式:{{ optionTextHighlightClassValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">result-text-class:单选结果文字样式</text>
			<uni-combox
				:options="gradeOptions"
				v-model="resultTextClassValue"
				result-text-class="demo-result-text"
			/>
			<text class="result-text">当前选择:{{ resultTextClassValue }}</text>
		</view>

		<view class="section">
			<text class="section-title">大量候选</text>
			<uni-combox
				:options="largeOptions"
				placeholder="请选择编号"
				v-model="largeValue"
			/>
			<text class="result-text">当前选择:{{ largeValue }}</text>
		</view>

		<view class="section">
			<text class="group-title">事件示例</text>
		</view>

		<view class="section">
			<text class="section-title">update:modelValue:值更新时触发</text>
			<uni-combox
				:options="cityOptions"
				v-model="updateEventValue"
				placeholder="请选择城市"
				@update:modelValue="onUpdateModelValue"
			/>
			<text class="result-text">事件值:{{ updateEventText }}</text>
		</view>

		<view class="section">
			<text class="section-title">selectchange:从候选项选中时触发</text>
			<uni-combox
				:options="statusOptions"
				v-model="selectEventValue"
				placeholder="请选择状态"
				@selectchange="onSelectChange"
			/>
			<text class="result-text">事件值:{{ selectEventText }}</text>
		</view>

	</scroll-view>
</template>

<script setup lang="ts">
const optionsValue = ref<string>('')
const placeholderValue = ref<string>('')
const disabledValue = ref<string>('三年级')
const arrowClassValue = ref<string>('')
const optionsViewClassValue = ref<string>('')
const optionTextClassValue = ref<string>('')
const optionTextHighlightClassValue = ref<string>('杭州')
const resultTextClassValue = ref<string>('三年级')
const updateEventValue = ref<string>('')
const updateEventText = ref<string>('未触发')
const selectEventValue = ref<string>('')
const selectEventText = ref<string>('未触发')
const city = ref<string>('杭州')
const largeValue = ref<string>('')

const gradeOptions: string[] = [
	'一年级',
	'二年级',
	'三年级',
	'四年级',
	'五年级',
	'六年级',
	'初一',
	'初二',
	'初三'
]

const cityOptions: string[] = [
	'北京',
	'上海',
	'广州',
	'深圳',
	'杭州',
	'南京',
	'苏州',
	'成都',
	'重庆',
	'武汉',
	'西安',
	'郑州'
]

const statusOptions: string[] = [
	'待处理',
	'处理中',
	'已完成',
	'已取消'
]

const largeOptions = computed(() : string[] => {
	const list: string[] = []
	for (let i = 1; i <= 120; i++) {
		const value = i < 10 ? `编号 00${i}` : (i < 100 ? `编号 0${i}` : `编号 ${i}`)
		list.push(value)
	}
	return list
})

function onUpdateModelValue(value : string) {
	updateEventText.value = value == '' ? '空字符串' : value
	console.log('combox update:modelValue:', value)
}

function onSelectChange(value : string) {
	selectEventText.value = value
	console.log('combox selectchange:', value)
}

function onCityChange(value : string) {
	console.log('city selectchange:', value)
}
</script>

<style>
.page {
	flex: 1;
	padding: 16px;
}

.section {
	margin-bottom: 24px;
}

.page-title {
	font-size: 20px;
	font-weight: bold;
	color: var(--text-color, #1f2937);
	margin-bottom: 8px;
}

.page-desc {
	font-size: 14px;
	line-height: 22px;
	color: var(--text-color, #64748b);
	opacity: 0.7;
}

.group-title {
	font-size: 18px;
	font-weight: bold;
	color: var(--text-color, #111827);
	margin-top: 4px;
}

.section-title {
	font-size: 16px;
	font-weight: bold;
	color: var(--text-color, #1f2937);
	margin-bottom: 10px;
}

.result-text {
	font-size: 13px;
	color: var(--text-color, #64748b);
	opacity: 0.7;
	margin-top: 8px;
}

.custom-input {
	flex: 1;
	width: 100%;
	height: 22px;
	font-size: 14px;
	color: var(--text-color, #1f2937);
	background-color: transparent;
}

.demo-arrow {
	border-right-color: var(--tips-color, #16a34a);
	border-bottom-color: var(--tips-color, #16a34a);
	border-right-width: 2px;
	border-bottom-width: 2px;
}

.demo-options-view {
	border-color: var(--tips-border-color, #2563eb);
	border-width: 2px;
	background-color: var(--tips-background-color, #eff6ff);
}

.demo-option-text {
	color: var(--tips-color, #7c3aed);
	font-weight: bold;
}

.demo-option-highlight {
	color: var(--tips-color, #dc2626);
	font-weight: bold;
}

.demo-result-text {
	color: var(--tips-color, #2563eb);
	font-weight: bold;
}
</style>

# 参见