<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) }]"> {{ 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: 'code'} } }, // 是否多选 multiple: 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 } if (this.multiple) { if (this.innerValue.includes(item[this.fieldNames.value])) { this.innerValue = this.innerValue.filter(e => e !== item[this.fieldNames.value]) } else { this.innerValue.push(item[this.fieldNames.value]) } } else { this.innerValue = item[this.fieldNames.value] } this.$emit('update:value', this.innerValue) this.$emit('change', this.innerValue, item) }, // 是否选中 isSelect(item){ 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; 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); } </style>