二话不说,我直接上代码
<template>
<div class="dh-field">
<div class="van-hairline--bottom">
<van-field
v-model="resultLabel"
v-bind="$attrs"
readonly
:label="label"
:is-link="$attrs.disabled === undefined"
error-message-align="right"
input-align="left"
class="dh-cell"
@click="showPopu($attrs.disabled)"
:rules="[{ required: require, message: requireMessage }]"
/>
<van-popup
v-model:show="show"
position="bottom"
class=""
:style="{ height: '30%' }"
>
<div class="van-picker__toolbar">
<button type="button" class="van-picker__cancel" @click="cancel">
取消
</button>
<div class="van-ellipsis van-picker__title">{{ $attrs.label }}</div>
<button type="button" class="van-picker__confirm" @click="onConfirm">
确认
</button>
</div>
<div style="max-height: 264px; overflow-y: auto">
<!-- <van-field
v-if="isSearch"
v-model="searchVal"
input-align="left"
placeholder="搜索"
@input="search"
@click="toggleAll"
/> -->
<van-cell ref="checkAll" title="全选" clickable @click="toggleAll">
<template #right-icon>
<div>
<van-checkbox v-model="checkedAll" name="all" />
</div>
<!-- @click="toggleAll" -->
</template>
</van-cell>
<van-checkbox-group
ref="checkboxGroup"
v-model="checkboxValue"
@change="change"
>
<van-cell-group>
<van-cell
v-for="(item, index) in columnsData"
:key="item[option.value]"
:title="item[option.label]"
clickable
@click="toggle(index)"
>
<!-- @click="toggle(index)" -->
<template #right-icon>
<div @click="toggle(index)">
<van-checkbox ref="checkboxes" :name="item[option.value]" />
</div>
</template>
</van-cell>
</van-cell-group>
</van-checkbox-group>
</div>
</van-popup>
</div>
</div>
</template>
<script>
export default {
name: "VanFieldCheckbox",
model: {
prop: "selectValue",
},
props: {
require: {
type: Boolean,
default: true,
},
requireMessage: {
type: String,
default: "此处显示校验内容",
},
label: {
type: String,
default: "标题",
},
columns: {
type: Array,
default: function () {
return [];
},
},
selectValue: {
type: Array,
default: function () {
return [];
},
},
option: {
type: Object,
default: function () {
return { label: "label", value: "value" };
},
},
// 是否支持搜索
isSearch: {
type: Boolean,
default: true,
},
},
computed: {
resultLabel: {
get() {
const res = this.columns.filter((item) => {
return this.resultValue.indexOf(item[this.option.value]) > -1;
});
const resLabel = res.map((item) => {
return item[this.option.label];
});
return resLabel.join(",");
},
set() {},
},
},
data() {
return {
show: false,
searchVal: "",
columnsData: JSON.parse(JSON.stringify(this.columns)),
checkboxValue: JSON.parse(JSON.stringify(this.selectValue)),
checkedAll: false,
resultValue: JSON.parse(JSON.stringify(this.selectValue)),
};
},
methods: {
// 搜索
search(val) {
if (val) {
this.columnsData = this.columnsData.filter((item) => {
return item[this.option.label].indexOf(val) > -1;
});
} else {
this.columnsData = JSON.parse(JSON.stringify(this.columns));
}
},
getData(val) {
const res = this.columnsData.filter((item) => {
return val.indexOf(item[this.option.value]) > -1;
});
return res;
},
onConfirm() {
this.resultValue = this.checkboxValue;
this.show = !this.show;
this.$emit("confirm", this.resultValue, this.getData(this.resultValue));
},
change(val) {
this.$emit("change", val, this.getData(this.resultValue));
},
cancel() {
this.show = !this.show;
this.$emit("cancel", this.resultValue);
},
toggle(index) {
this.$refs.checkboxes[index].toggle();
},
toggleAll(all) {
console.log(all);
// this.checkedAll = !this.checkedAll;
this.$refs.checkboxGroup.toggleAll(this.checkedAll);
},
showPopu(disabled) {
console.log(disabled);
this.columnsData = JSON.parse(JSON.stringify(this.columns));
this.checkboxValue = JSON.parse(JSON.stringify(this.selectValue));
this.resultValue = JSON.parse(JSON.stringify(this.selectValue));
if (disabled !== undefined && disabled !== false) {
return false;
} else {
this.show = !this.show;
}
},
},
watch: {
selectValue: function (newVal) {
this.resultValue = newVal;
},
resultValue(val) {
this.searchVal = "";
this.columnsData = JSON.parse(JSON.stringify(this.columns));
this.$emit("input", val);
},
columnsData: {
handler(val) {
if (val.length && val.length === this.checkboxValue.length) {
this.checkedAll = true;
} else {
this.checkedAll = false;
}
},
immediate: true,
},
checkboxValue: {
handler(val) {
if (val.length && val.length === this.columnsData.length) {
this.checkedAll = true;
} else {
this.checkedAll = false;
}
},
immediate: true,
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .van-cell__title {
padding: 0 0.3rem;
}
.dh-field {
padding: 0;
background: #fff;
.dh-cell.van-cell {
padding: 10px 0;
}
.dh-cell.van-cell--required::before {
left: -8px;
}
.van-popup {
border-radius: 20px 20px 0 0;
}
}
</style>
使用方法
<SelectCheckBox
label="客户业务"
placeholder="请选择客户业务"
requireMessage="请选择客户业务"
:columns="customerBusinessAll"
:selectValue="from.customerBusiness"
@confirm="getCustomerBusiness"
label-width="100"
:option="{ label: 'label', value: 'value' }"
/>
columns的数据结构可以在option上定义好
最终实现效果如下
全选上可放搜索,组件中我注释了