背景
在公司遇到一个奇怪的需求,用户可以自定义下拉框的内容,也就是说用户看到下拉框里面没有自己喜欢的选项,他可以对已有的选项进行修改,或者直接自己新增;当时感觉还很奇葩,后来想想,也许是为了给用户更高的选择自由度吧,没有你喜欢的选项,你可以自己新建一个😁😁😄。
实现原理
这里是
vue2 + element-ui为基础
实现方式主要是通过自定义
option的方式实现,代码主要分为三块:编辑区、选择区、添加自定义模板区
代码: 目前不支持搜索功能
<template>
<div class="">
<el-select
v-model="value"
placeholder="请选择"
style="width: 50%; position: relative;"
@visible-change="visibleChange($event)"
@change="selectOption"
:loading="selLoadingBool"
loading-text="数据更新中...">
<el-option
v-for="item in materialTitleListData"
:key="item.id"
:label="item.content"
:value="item.content"
:disabled="disableBool"
:style="{ height: item.id === -99 ? '0px' : '', marginBottom: item.id === materialTitleListData[materialTitleListData.length - 1].id ? '40px' : '' }">
<!-- 编辑区 -->
<div v-if="item.id === itemId">
<el-input
v-model="inputValue"
@keyup.enter.native="updateTemplete(inputValue, item.id, '')"
:maxlength="maxlength"
show-word-limit
:placeholder="placeholder"
style="width:300px; margin:0"/>
<div style="float: right;">
<el-button
@click.stop="updateTemplete(inputValue, item.id, '')"
icon="el-icon-check" type="text"
style="fontSize: 15px;padding: 0;"/>
<el-button
@click.stop="updateTemplete(inputValue, item.id, 'cancle')"
icon="el-icon-close"
type="text"
style="color:red;fontSize: 15px;padding: 0;"/>
</div>
</div>
<!-- 选择区 -->
<div v-else>
<span style="float: left">{{ item.content }}</span>
<div style="float: right; fontSize: 13px;">
<el-button
:disabled="disableBool"
@click.stop="getMaterialInfo(item)"
icon="el-icon-edit"
type="text"
style="fontSize: 15px;"/>
<el-button
:disabled="disableBool"
@click.stop="deleteItemTitle(item)"
icon="el-icon-delete"
type="text"
:style="{ fontSize: '15px', color: disableBool ? '#C0C4CC' : 'red' }"/>
</div>
</div>
</el-option>
<!-- 添加自定义模板区 -->
<div style="position: absolute; bottom:0px;width: 100%;height: 45px;background-color: #fff;z-index: 999;">
<div v-if="addCustomTempleteBool">
<el-input
v-model="addCustomValue"
@input="getCustomValue"
@keyup.enter.native="saveTemplate"
style="margin:6px 0 0 20px;width:300px;"
:maxlength="maxlength"
show-word-limit
:placeholder="placeholder" />
<div style="float: right; margin: 10px 20px 0 0;">
<el-button
@click.stop="saveTemplate"
icon="el-icon-check" type="text"
style="fontSize: 15px;padding: 0;"/>
<el-button
@click.stop="addCustomTempleteBool = false, disableBool = false, addCustomValue = ''"
icon="el-icon-close"
type="text"
style="color:red;fontSize: 15px;padding: 0;"/>
</div>
</div>
<el-button v-else
:disabled="disableBool"
type="text"
@click="addCustomTempleteBool = true, disableBool = true"
class="addCustom">
{{ bottomName }}
</el-button>
</div>
</el-select>
</div>
</template>
<script>
/**
* 接收的参数
* @prop materialTitleList:array select数据源
* @prop bottomName:string 自定义标题模板名称
* @prop selLoadingBool:boolean 下拉框的加载状态
* @prop maxlength:number 文字最大长度
* 抛出的事件
* @prop selectOption 选中的option
* @prop updateTemplete 更新当前修改的模板
* @prop deleteItemTitle 删除当前option
* @prop saveTemplate 保存添加的模板
*/
export default {
name: 'customizeSelect',
props: {
materialTitleList: {
type: Array,
default: () => ([])
},
bottomName: {
type: String,
default: ' + 添加自定义标题模板'
},
selLoadingBool: {
type: Boolean,
default: false
},
maxlength: {
type: Number,
default: 35
}
},
data() {
return {
placeholder: '点击“√”或回车保留模板',
value: '',
disableBool: false,
itemId: -1,
inputValue: '',
addCustomTempleteBool: false,
addCustomValue: '',
materialTitleListData: []
};
},
watch: {
materialTitleList: {
handler(val) {
if (val.length === 0) {
// 当没有数据传来时,需要一条 假数据 进行占位
this.materialTitleListData = [{id: -99, content: '--'}];
} else {
this.materialTitleListData = val;
}
},
immediate: true,
deep: true
}
},
methods: {
// 下拉/收起事件
visibleChange(bool) {
if (!bool) {
this.initModify();
}
},
// 选中的option
selectOption(e) {
this.$emit('selectOption', e);
},
// 取消/更新option的修改
updateTemplete(val, id, type) {
if (type !== 'cancle') {
this.$emit('updateTemplete', val, id);
}
this.initModify();
},
// 获取每条数据信息
getMaterialInfo(item) {
this.disableBool = true;
this.itemId = item.id;
this.inputValue = item.content;
},
// 删除当前项
deleteItemTitle(item) {
this.$emit('deleteItemTitle', item);
},
// 自定义模板模块
// 获取自定义模板的值
getCustomValue(e) {
this.addCustomValue = e;
},
// 点击“√”或回车保留模板
saveTemplate() {
this.$emit('saveTemplate', this.addCustomValue);
this.initModify();
},
// 下拉框初始化
initModify() {
this.itemId = -1;
this.addCustomTempleteBool = false;
this.disableBool = false;
this.addCustomValue = '';
}
},
};
</script>
<style lang="scss" scoped>
.addCustom {
width: 100%;
height: 100%;
line-height: 100%;
}
</style>