由于项目在vue的开发框架下,因此使用ElementUI组件库进行实现。
我希望可选择可编辑的下拉框右侧有跟下拉框一样的箭头,并且在未输入任何内容时,点击该框体会出现选择列表进行填充数据的选择,点击选中数据后列表消失,数据内容出现在框体中,并且点击可编辑,编辑时不会再有任何列表出现,当清空框体后候选列表可出现。
但是ElemnetUI组件库中并没有完全符合需求的组件。
只有不可编辑的下拉框el-select(缺少可编辑功能)
或是只能编辑的el-input(缺少下拉选择功能)
或是只有输入出现匹配提示的el-autocomplete(缺少下拉箭头和展开收起功能,点击已有内容会再次出现候选列表)
网上也没找到特别符合需求的,因此打算在输入出现匹配提示的el-autocomplete基础上进行修改。
在设计上增加了下拉框的箭头,因此要根据候选列表的显示和隐藏去绑定箭头的方向,让它们两者互相联动互相影响。
<el-autocomplete
v-model="form.processes"
:fetch-suggestions="queryProcesses"
placeholder="请输入进程数"
clearable
:style="{width: '100%'}"
ref="processesAutocomplete"
@focus="handleProcessesFocus"
@blur="handleProcessesBlur"
@clear="handleProcessesClear"
class="processes-autocomplete"
:class="{ 'is-empty': !form.processes, 'is-dropdown-visible': isProcessesDropdownVisible }"
@click.native="handleProcessesInputClick"
>
<i
slot="suffix"
:class="['el-input__icon', 'el-icon-arrow-down', 'processes-arrow', { 'is-reverse': isProcessesDropdownVisible }]"
@click.stop="toggleProcessesDropdown"
></i>
</el-autocomplete>
自定义下拉箭头:
使用 <i> 元素作为后缀图标,设置下拉箭头
动态类绑定:
processes-autocomplete:基础样式类
'is-empty': !form.processes:当输入框为空时添加 is-empty 类
'is-dropdown-visible': isProcessesDropdownVisible:当下拉列表显示时添加该类
箭头图标控制:
processes-arrow:箭头基础样式
'is-reverse': isProcessesDropdownVisible:当下拉列表显示时旋转180度
事件处理:
@click.native="handleProcessesInputClick":处理输入框点击
@click.stop="toggleProcessesDropdown":点击箭头切换下拉状态
在data()中添加以下示例内容:
isProcessesDropdownVisible: false,
processesOptions: [
{ value: "30", label: '30' },
{ value: "60", label: '60' },
{ value: "120", label: '120' }
],
Methods部分要增加以下内容:
控制只在输入框为空时显示预定义选项。
queryProcesses(queryString, cb) {
// 只显示预定义的选项,不根据输入内容过滤
// 只有当输入框为空时才显示所有选项
if (!queryString) {
cb(this.processesOptions);
} else {
// 当有输入内容时,不显示任何建议列表
cb([]);
}
},
延迟隐藏下拉列表,避免用户点击选项时立即隐藏。
handleProcessesBlur() {
// 延迟隐藏下拉列表,避免点击选项时立即隐藏
setTimeout(() => {
this.isProcessesDropdownVisible = false;
}, 150);
},
清空输入内容时显示下拉列表。
handleProcessesClear() {
this.isProcessesDropdownVisible = true;
},
根据输入框是否为空决定是否切换下拉状态。
// 处理输入框点击事件
handleProcessesInputClick() {
// 如果输入框有内容,只聚焦不切换下拉状态
if (this.form.processes) {
return;
}
// 如果输入框为空,切换下拉状态
this.toggleProcessesDropdown();
},
控制下拉列表的显示/隐藏,并相应地设置建议选项和焦点。
// 切换下拉列表显示状态
toggleProcessesDropdown() {
this.isProcessesDropdownVisible = !this.isProcessesDropdownVisible;
this.$nextTick(() => {
if (this.$refs.processesAutocomplete) {
if (this.isProcessesDropdownVisible) {
// 立即显示下拉列表
this.$refs.processesAutocomplete.suggestions = this.processesOptions;
// 聚焦到输入框
this.$refs.processesAutocomplete.focus();
} else {
// 隐藏下拉列表并取消输入框焦点
// 清空建议列表来隐藏下拉菜单
if (this.$refs.processesAutocomplete.suggestions) {
this.$refs.processesAutocomplete.suggestions = [];
}
// 取消输入框焦点
this.$refs.processesAutocomplete.$el.querySelector('input').blur();
}
}
});
},
样式文件如下:
<style scoped>
.processes-autocomplete.is-empty ::v-deep .el-input__inner {
padding-right: 30px;
}
.processes-arrow {
transition: transform 0.25s ease-in-out;
cursor: pointer;
line-height: 30px;
color: #C0C4CC;
font-size: 14px;
}
.processes-arrow.is-reverse {
transform: rotate(-180deg);
}
.processes-autocomplete:not(.is-empty) ::v-deep .processes-arrow {
display: none;
}
/* 当鼠标按下时保持箭头状态不变 */
.processes-arrow:active {
transform: rotate(-180deg) !important;
}
</style>
箭头方向与下拉状态联动:
下拉列表隐藏时:箭头向下(默认状态)
下拉列表显示时:箭头向上(通过 is-reverse 类实现)
箭头显示与输入内容联动:
输入框为空时:显示箭头
输入框有内容时:隐藏箭头显示清空图标
用户体验优化:
点击箭头或空输入框可切换下拉状态
有内容时点击输入框不会改变下拉状态
延迟隐藏避免误操作
平滑的旋转动画效果