vue 封装el-select多选下拉框(可用输入框搜索过滤)
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
vue 封装el-select多选下拉框(可用输入框搜索过滤)
下拉筛选效果如下
代码部分
html部分
- 创建多选组件 mSelect.vue
<template>
<el-select
ref="select"
v-model="hValue"
multiple
collapse-tags
:clearable="clearable"
:disabled="disabled"
:placeholder="placeholder"
:popper-class="selectInfo.align == 'left'
? 'select-default select-text-align-left no-empty'
: 'select-default no-empty'
"
:key="poperKeyValue"
:value-key="valueKey"
@blur="handleBlur"
@change="handleChange"
@clear="handleClear"
@focus="handleFocus"
@remove-tag="handleRemoveTag"
@visible-change="handleVisibleChange"
>
<el-input
class="filter-input"
v-model.trim="hFilterVal"
v-if="filterable"
:class="selectInfo.options.length == 0 ? 'filter-input-mb' : ''"
></el-input>
<el-checkbox-group v-model="hValue">
<el-option
v-for="(item, index) in selectInfo.options"
:key="index"
:label="
selectInfo.prop && selectInfo.prop.label
? item[selectInfo.prop.label]
: item.name
"
:disabled="item.disabled"
:value="
selectInfo.prop && selectInfo.prop.value
? item[selectInfo.prop.value]
: item.id
"
>
<el-checkbox
style="pointer-events: none"
:label="
selectInfo.prop && selectInfo.prop.value
? item[selectInfo.prop.value]
: item.id
"
>{{
selectInfo.prop && selectInfo.prop.label
? item[selectInfo.prop.label]
: item.name
}}
</el-checkbox>
</el-option>
</el-checkbox-group>
</el-select>
</template>
<script>
export default {
name: "HSelectMul",
props: {
placeholder: String,
selectInfo: {
type: Object,
default() {
return {
align: "left",
options: [],
prop:{
label:'name',
value:'id'
}
};
}
},
filterVal:{
type:String,
value:''
},
clearable: {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
filterable: {
type: Boolean,
default: true
},
value: {
type: [String, Number, Array, Boolean],
required: true
},
valueKey: String,
keyValue: {
type: String,
default: "select-single"
}
},
data() {
return {
poperKeyValue: ""
};
},
computed: {
hValue: {
get() {
let value = [];
if (this.value instanceof Array) {
this.value.forEach(key => {
if (this.checkValueExisting(key)) {
value.push(key);
}
});
}
return value;
},
set(value) {
this.$emit("input", value);
}
},
hFilterVal: {
get() {
return this.filterVal;
},
set(value) {
this.$emit("input-search", value);
}
},
},
watch: {
keyValue(val) {
this.poperKeyValue = val;
}
},
methods: {
checkValueExisting(value) {
let key = this.selectInfo.prop&&this.selectInfo.prop.value?this.selectInfo.prop.value:'id'
if(this.filterable) {
if (this.selectInfo.filterOptions instanceof Array) {
let index = this.selectInfo.filterOptions.findIndex(
item => item[key] === value,
this
);
return index > -1;
}
} else {
if (this.selectInfo.options instanceof Array) {
let index = this.selectInfo.options.findIndex(
item => item[key] === value,
this
);
return index > -1;
}
}
return false;
},
handleBlur(event) {
this.$emit("blur", event);
},
handleChange(value) {
this.$emit("change", value);
},
handleClear() {
this.$emit("clear");
},
handleFocus(event) {
this.$emit("focus", event);
},
handleRemoveTag(tag) {
this.$emit("remove-tag", tag);
},
handleVisibleChange(visible) {
this.$emit("visible-change", visible);
}
}
};
</script>
<style lang="scss" scoped></style>
- 在父组件中引用
<template>
<div>
<m-select
:select-info="info"
v-model="formData.form[info.field]"
:filter-val="info.filterVal"
@input-search="dropDownSearchTop"
@change="changeSelect"
>
</m-select>
</div>
</template>
<script>
import MSelect from "@/harley-ui/selectMultiple/index";
export default {
data() {
return {
info: {
filterOptions:[],
options: [],
filterVal: '',
chooseSelectList:[],
prop:{
label:'name',
value:'id'
}
}
}
},
components:{MSelect},
methods:{
changeSelect(val) {
console.log(val, "kkkkk");
this.info.chooseSelectList = [];
for (let i = 0; i < info.filterOptions.length; i++) {
for (let j = 0; j < val.length; j++) {
let value = info.prop && info.prop.value ? info.prop.value : "id";
if (val[j] === info.filterOptions[i][value]) {
info.chooseSelectList.push(info.filterOptions[i]);
}
}
}
},
dropDownSearchTop(val) {
this.info.filterVal = val;
if (this.info.filterVal === "") {
this.info.options = JSON.parse(JSON.stringify(this.info.filterOptions));
return;
}
let list = [];
if (this.info.chooseSelectList.length > 0) {
list = info.filterOptions.filter(item => {
let value = this.info.prop && this.info.prop.value ? this.info.prop.value : "id";
return info.chooseSelectList.every(el => el[value] != item[value]);
});
} else {
list = JSON.parse(JSON.stringify(this.info.filterOptions));
}
this.info.options = this.info.chooseSelectList.concat(
list.filter(item => {
let name = this.info.prop && this.info.prop.label ? this.info.prop.label : "name";
return item[name].includes(this.info.filterVal);
})
);
},
}
}
</script>
css部分
.select-default {
background-color: #43504a;
color: #45494d;
border: 1px solid #43504a;
&.select-text-align-left {
.el-scrollbar__wrap {
.el-select-dropdown__list {
.el-select-dropdown__item {
text-align: left;
}
}
}
}
&.no-empty {
.el-scrollbar {
display: block !important;
.el-scrollbar__wrap {
// overflow-y: scroll;
// overflow-x: hidden;
// margin-bottom: vh(-6) !important;
// margin-right: vw(-6) !important;
.el-select-dropdown__list {
.filter-input {
height: 50px;
width: 84%;
margin-bottom: 30px;
margin-left: 30px;
&.filter-input-mb {
margin-bottom: 10px;
}
.el-input__inner {
width: 100%;
height: 100%;
color:#fff;
border: 1px solid #fff !important;
font-size: 24px;
}
}
}
}
}
}
.el-scrollbar__wrap {
max-height: 404px;
.el-select-dropdown__list {
padding: 6px 0;
.el-checkbox-group {
display: flex;
justify-content: center;
flex-direction: column;
height: 100%;
.el-checkbox {
width: fit-content;
padding: 0;
display: inline-flex;
align-items: center;
height: 100%;
font-size: 24px;
margin-right: vw(30);
.el-checkbox__label {
font-size: 24px;
padding-left: 13px;
color: #fff;
display: flex;
align-items: center;
height: 100%;
}
.el-checkbox__input {
display: inline-flex;
align-items: center;
justify-content: center;
&.is-checked {
.el-checkbox__inner {
background: url("勾选的图片");
width: 33px;
height: 33px;
border: none;
}
+ .el-checkbox__label {
color: #fff;
}
}
&.is-disabled {
.el-checkbox__inner {
background: url("禁用的图片");
width: 33px;
height: 33px;
}
&.is-checked {
.el-checkbox__inner {
background: url("勾选的图片");
width: 33px;
height: 33px;
border: none;
}
+ .el-checkbox__label {
color: #fff;
}
}
}
.el-checkbox__inner {
background: url("未勾选的图片");
width: 33px;
height: 33px;
}
}
}
}
.el-select-dropdown__item {
font-size: 24px;
padding: 0 20px;
color: #fff;
height: 38px;
line-height: 38px;
text-align: center;
font-weight: 100;
margin-bottom: 20px;
box-sizing: border-box;
cursor: pointer;
&:last-child {
margin-bottom: 0;
}
&.is-disabled {
color: #75837c;
cursor: not-allowed;
&:hover {
background: transparent !important;
color: #75837c !important;
font-weight: 100;
}
.el-checkbox {
opacity: 0.7;
}
}
&:hover {
background: #808c87 !important;
color: #fff !important;
height: 38px;
}
&.hover {
background: transparent !important;
color: #fff !important;
height: 38px;
&:hover {
background: #808c87 !important;
color: #fff !important;
height: 38px;
}
}
&.selected {
background: #808c87 !important;
color: #fff !important;
height: 38px;
&.hover {
background: #808c87 !important;
}
}
}
}
}
}
传参属性解读
- filterOptions — 存储原始的下拉绑定的list,用来过滤(输入框改变的时候需要取到所有的数据进行筛选然后展示,所以该属性需要存储所有的下拉选的值)
- options — 下拉选绑定的list
- filterVal — 输入框绑定的值
- prop — 获取选中取值的key用那个字段
- chooseSelectList — 现在已经选中的下拉集合(在dropDownSearchTop方法中,之所以要拼接上chooseSelectList.concat是为了避免绑定的options中没有之前选中的值,页面展示不出来之前选中值的名称)
类名解读
- no-empty
- 当我们模糊搜索时如果未匹配到相符合的数据,el-select展示暂无数据且将el-scrollbar下的内容全部隐藏掉,所以我们需要先把el-scrollbar样式设为block,否则输入框会被隐藏掉
GitHub 加速计划 / vu / vue
207.52 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:1 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 3 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 3 个月前
更多推荐
已为社区贡献14条内容
所有评论(0)