要实现一个自定义的下拉框,并且包含你提到的几个要点
我们这里需要使用到Vue3模板、计算属性、方法和事件监听等功能。
以下是一个简化的实现思路
-
输入框的显示与隐藏:
- 使用
v-if
或v-show
来控制输入框的显示与隐藏。 - 当用户点击下拉框但未选择具体项(比如点击了自定义选项),显示输入框。
- 当用户选择具体项或确认自定义输入后,隐藏输入框。
- 使用
-
下拉框宽度自适应:
- 使用CSS来控制下拉框的宽度,可以使用
min-width
、max-width
或width: 100%
等来实现自适应。 - 确保下拉框容器的宽度设置能够正确影响内部的
el-option
等元素。
- 使用CSS来控制下拉框的宽度,可以使用
-
自定义的数据回显:
- 监听输入框的
input
事件,实时更新自定义数据。 - 当用户从下拉框中选择项时,更新
v-model
绑定的值。 - 使用计算属性或方法来合并显示默认选项和自定义选项。
- 监听输入框的
-
接口数据要回显对应的次数:
- 假设接口返回的数据包含次数信息,可以在
el-option
的:label
中使用模板字符串来显示次数。 - 例如:
:label="
item.label({item.count}次)"
。
- 假设接口返回的数据包含次数信息,可以在
-
优化与交互:
- 当用户选择自定义选项(值为0)时,显示输入框并聚焦。
- 提供一个"确认"按钮来确认自定义输入,并添加到下拉框的选项中。
- 使用Vue的
ref
和$refs
来访问DOM元素,实现输入框的聚焦。
这里是具体的dom样式,这里不是频繁修改就使用v-if,在下拉框最下面显示一个自定义次数选项,给值0,并进行监听,如果是0就展示输入框并收起下拉框,还有默认聚焦输入框,只有点击确认按钮才会确认并新增到options里面。
ini
<template>
<div>
<el-select
v-model="value"
placeholder="Select"
class="relative"
:style="{ width: selectWidth }"
@change="handleSelectChange"
@visible-change="visibleChange"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
<el-option
key="custom"
label="自定义次数"
:value="0"
/>
</el-select>
<div v-if="showInput" class="input-container absolute">
<el-input
ref="inputRef"
v-model="customValue"
placeholder=""
style="width: 80px;margin-right: 16px;"
/>
<el-button type="text" @click="addCustomOption">
确认
</el-button>
</div>
</div>
</template>
监听到下拉框显示就关闭输入框
php
// 下拉框显示关闭输入框
function visibleChange(val: boolean) {
if (val) {
showInput.value = false
}
}
调整下拉框宽度,如果是自定义次数,宽度就是120px,可以显示全自定义次数的字
ini
// 调整下拉框宽度
function adjustSelectWidth(val: number) {
const tempDiv = document.createElement('div')
tempDiv.style.position = 'absolute'
tempDiv.style.visibility = 'hidden'
tempDiv.style.width = 'auto'
tempDiv.style.fontSize = '14px'
document.body.appendChild(tempDiv)
tempDiv.innerHTML = getLabel(val)
selectWidth.value = val ? `${tempDiv.clientWidth + 60}px` : '120px'
document.body.removeChild(tempDiv)
}
下拉框选择之后的输入框展示与隐藏
kotlin
// 处理选择变化
function handleSelectChange(val: number) {
if (val === 0) { // 假设 0 是自定义选项的值
showInput.value = true
customValue.value = null
adjustSelectWidth(val)
// 输入框聚焦
nextTick(() => {
const input = inputRef.value as HTMLInputElement
input.focus()
})
}
else {
showInput.value = false
adjustSelectWidth(val)
}
}
添加自定义选项
ini
function addCustomOption() {
if (customValue.value !== null) {
const customLabel = getLabel(customValue.value)
options.value.push({ value: customValue.value, label: customLabel })
value.value = customValue.value
showInput.value = false
}
}
监控 props.value,动态添加不存在的选项
scss
watch(
() => props.value,
(newVal) => {
ensureValueInOptions(newVal)
adjustSelectWidth(newVal)
},
{ immediate: true },
)
确保传递的动态值在 options 中存在
scss
function ensureValueInOptions(val: number) {
if (!options.value.some(option => option.value === val)) {
val && options.value.push({
value: val,
label: getLabel(val),
})
}
}
// 初始检查
ensureValueInOptions(props.value)
最终的效果
去掉输入框的边框,以及输入框的位置
css
.input-container {
display: flex;
align-items: center;
border-radius: 8px;
background: #fff;
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.12);
padding: 15px;
z-index: 9999;
}
::v-deep(.el-input__wrapper) {
box-shadow: none;
}
总结:
showInput
: 新增的ref
,控制是否显示el-input
。customValue
: 用于存储自定义输入的值。handleSelectChange
: 处理el-select
选择变化的函数。如果选择的是自定义选项(假设值为0
),则显示el-input
。addCustomOption
: 当自定义值输入完成后,将其添加到options
列表中,并设置为当前选中的值。
通过这种方式,你可以在下拉框中添加一个自定义选项,点击该选项后显示输入框以输入自定义次数,并将输入的值添加到选项列表中进行选择,有一些样式还有其他细节也可以根据自己的需要进行一个补充,大致的逻辑就是这样。