Element UI 自定义el-cascader多选组件
需求
element ui 中的 el-cascader 组件,多选之后,有两个问题,高度撑开输入框,并且没有确定按钮
我现在需要一个下拉框,可以勾选数据,点击“确定”回显到输入框中。输入框中的数据可以横向滚动。实现结果如下图:


实现
<el-cascader class="custom-el-cascader"filterable :props="{ value: 'id', label: 'name', emitPath: false, multiple: true, checkStrictly: true, }" ref="select"placeholder="选择/搜索班级"@remove-tag="onEnterSearch"v-model="ids" @visible-change="visibleChange" :options="list" @clear="onEnterSearch" clearable></el-cascader>
其中 visibleChange
visibleChange(visible) {console.log(visible)// 下拉框显示隐藏if (visible) {const ref = this.$refs.selectlet popper = ref.$refs.popperif (popper.$el) popper = popper.$el// 判断是否有添加按钮if (!Array.from(popper.children).some(v => v.className === 'select-btn-box')) {// 插入按钮let el = document.createElement('div')let confirmBtn = document.createElement('button')el.className = 'select-btn-box'confirmBtn.className = 'select-confirm-mini-btn'confirmBtn.innerText = '确定'el.appendChild(confirmBtn)confirmBtn.onclick = () => {this.$refs.select.dropDownVisible = false; //监听值发生变化就关闭它if (this.data.classIds.length != 0) this.onEnterSearch();}popper.appendChild(el)}}},
其中visibleChange
函数中添加的css如:select-btn-box
、select-confirm-mini-btn
//自定义el-cascader
.custom-el-cascader {.el-cascader__tags {overflow-x: scroll;flex-wrap: nowrap;overflow-y: hidden;text-overflow: ellipsis;margin-left: 5px;}.el-input--medium .el-input__inner {padding-left: 18px;}// 隐藏滚动条.el-cascader__tags::-webkit-scrollbar {display: none;}
}
// 自定义el-cascader确定按钮
.select-btn-box {display: flex;border-top: 1px solid #dfe6ec;width: 100%;height: 44px;align-items: center;justify-content: flex-end;
}.select-confirm-mini-btn:hover {background-color: #339bfa;
}.select-confirm-mini-btn {display: inline-block;line-height: 1;white-space: nowrap;cursor: pointer;background: #fff;border: 1px solid #dcdfe6;-webkit-appearance: none;text-align: center;box-sizing: border-box;outline: none;margin: 0;transition: 0.1s;font-weight: 500;-moz-user-select: none;-webkit-user-select: none;-ms-user-select: none;padding: 12px 20px;font-size: 14px;border-radius: 4px;color: #fff;background-color: #0080f5;border-color: #409eff;padding: 7px 15px;font-size: 12px;border-radius: 3px;margin-right: 10px;
}
-
绑定
- 绑定
v-model
到ids
,并将其初始化为数组[]
- 绑定
-
可搜索与多选
- 启用
filterable
实现输入搜索。 - 在
:props
中:- value/label 映射:
{ value: 'id', label: 'name' }
。 - 扁平值:
emitPath: false
,仅返回最后一级的值。 - 多选:
multiple: true
。 - 父子独立:
checkStrictly: true
,父子节点可独立选择。
- value/label 映射:
- 启用
-
交互事件
@remove-tag="onEnterSearch"
:移除已选项时触发搜索。@clear="onEnterSearch"
:清空选择时触发搜索。@visible-change="visibleChange"
:展开下拉时,动态在下拉面板底部插入“确定”按钮,用于确认并关闭面板。
-
下拉面板“确定”按钮(自定义增强)
- 在
visibleChange
中,通过this.$refs.select.$refs.popper
取到弹层 DOM,插入一个.select-btn-box
容器与.select-confirm-mini-btn
按钮。 - 点击“确定”:
- 设置
this.$refs.select.dropDownVisible = false
主动关闭下拉。 - 若已选择项不为空,调用
onEnterSearch()
触发查询。
- 设置
- 作用:避免每次勾选立刻请求,改为集中确认后再搜索。
- 在
-
样式定制
- 根节点添加类名:
class="custom-el-cascader"
以便定制。 - 基础样式里对
el-cascader
设定min-width: 200px; white-space: nowrap;
,避免内容换行。 - 对
::v-deep .el-cascader__tags
设置横向滚动,标签过多时可左右滑动,并隐藏滚动条,避免挤压输入与产生视觉冲突。 - 为自定义底部按钮添加样式(
.select-btn-box
与.select-confirm-mini-btn
),与 ElementUI 风格一致。
- 根节点添加类名:
其中
const ref = this.$refs.select;let popper = ref.$refs.popper;if (popper.$el) popper = popper.$el;
ref.$refs.popper
:通过父组件的 $refs 获取名为 popper 的子组件实例
返回值为Vue 组件实例对象,当你需要调用子组件的方法或访问子组件的数据时使用
ref.$refs.popper.$el
:从已有的 Vue 组件实例中获取其对应的真实 DOM 元素,返回值为HTML DOM 元素,当你需要进行原生 DOM 操作时使用