<template> <div class="check-btn"> <div v-for="item in options" :key="item[fieldNames.value]" @click="onClick(item)" :class="['py-2 px-3 shrink-0 check-btn-item', { 'check-btn-item-active': isSelect(item) }, { 'check-btn-item-disabled': isDisabled(item) }, `text-align-${textAlign}`]" > {{ item[fieldNames.text] }} </div> </div> </template> <script> export default { name: 'CheckBtn', props:{ value: [String, Number, Array], // 选项 options: { default: () =>[] }, fieldNames: { type: Object, default: () => { return {text: 'name', value: 'value'} } }, // 点击取消选中 单选 clearable: { default: true }, // 是否多选 multiple: Boolean, textAlign: { default: 'center' }, // 关闭选中样式 activeStyleNone: Boolean }, emits: ['update:value', 'change'], data() { return { innerValue: undefined } }, created() { this.init() }, methods: { init() { this.innerValue = this.value this.multipleCheck() }, multipleCheck() { if (this.multiple) { if (this.value != null && !Array.isArray(this.value)) { console.warn('CheckBtn: multiple must be Array type') } this.innerValue = this.innerValue || [] } }, onClick(item){ if (this.isDisabled(item)) { return } const val = item[this.fieldNames.value] if (this.multiple) { if (this.innerValue.includes(val)) { this.innerValue = this.innerValue.filter(e => e !== val) } else { this.innerValue.push(val) } } else { if (this.clearable && this.innerValue === val) { this.innerValue = undefined } else { this.innerValue = val } } this.$emit('update:value', this.innerValue) this.$emit('change', this.innerValue, item) }, // 是否选中 isSelect(item){ if (this.activeStyleNone) { return false } if (this.multiple) { return this.innerValue.includes(item[this.fieldNames.value]) } else { return item[this.fieldNames.value] === this.innerValue } }, isDisabled(item){ return item.disabled } }, watch: { value: { handler(value) { this.innerValue = value this.multipleCheck() }, immediate: true }, } } </script> <style lang="less" scoped> .check-btn { display: flex; flex-wrap: wrap; row-gap: 10px; column-gap: 10px; .check-btn-item { border: 1px solid transparent; background-color: #FAFAFA; border-radius: 8px; text-align: center; transition: all .2s; } .check-btn-item-active { border: 1px solid var(--van-primary-color); background-color: #F0F6FF; color: var(--van-primary-color); } .check-btn-item-disabled { background-color: #F0F6FF; color: var(--van-primary-color); // opacity: 0.5; filter: grayscale(1); } .text-align-left { text-align: left; } .text-align-center { text-align: center; } .text-align-right { text-align: right; } } .check-btn.check-btn-workbench { .check-btn-item { border-radius: 30px; padding-top: 4px; padding-bottom: 4px; color: #595959; } .check-btn-item-active { color: var(--van-primary-color); } } // 圆角 .check-btn[round] { .check-btn-item { border-radius: 30px; } } // 每行排列个数 .check-btn[column-3] { .check-btn-item { width: calc(33.3% - 6.6px); } } .check-btn[column-2] { .check-btn-item { width: calc(50% - 5px); } } .check-btn[column-1] { .check-btn-item { width: 100%; } } </style>