CheckBtn.vue 4.1 KB
<template>
    <div class="flex flex-wrap 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
            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
            },
            immediate: true
        },
        
    }
}
</script>

<style lang="less" scoped>

.check-btn {
    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[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>