如何封装一款复选框组组件

696 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

TIP 👉 东边日出西边雨,道是无晴却有晴。唐·刘禹锡《竹枝词》

前言

在我们日常项目开发中,我们在做业务开发的时候会涉及到复选框组的功能,所以封装了这个复选框组的组件。

复选框组

属性

1. title
  • 复选框组的标题
  • 值为字符串类型
2. options
  • 复选项目数组
  • 必填

数组中对象示例:{ value: '01', text: '书', disabled:false}

  • value: 值
  • text: 显示的文字
  • disabled: 是否可用
3. value
  • 当前选中值
  • 值为数组类型

示例

<template>
  <div class="checkbox-wrap">
    <CheckboxGroup title="请选择银行:" :options="checkboxOptions" v-model="banks" @change="doChange"></CheckboxGroup>
    <div class="result">选择结果为:{{banks}}</div>
  </div>
</template>
<script>
import CheckboxGroup from '@/components/m/checkboxGroup/index.vue'
export default {
  name: 'CheckboxDemo',
  components: {
    BaseCheckbox
  },
  data () {
    return {
      banks: ['01', '03'],
      checkboxOptions: [
        { value: '01', text: '青莲使者' },
        { value: '02', text: '青莲使者' },
        { value: '03', text: '青莲使者' },
        { value: '04', text: '青莲使者' },
        { value: '05', text: '青莲使者', disabled: true }
      ]
    }
  },
  methods: {
    doChange (val) {
      console.log('触发change事件,value = ', val)
    }
  }
}
</script>
<style lang="scss" scoped>
.checkbox-wrap{
  font-size: 36px;
  line-height: 90px;
  .result{
    margin-top: 40px;
    padding: 0 40px;
  }
}
</style>

实现checkboxGroup.vue

<template>
  <div class="checkbox-group">
    <div class="checkbox-title">{{title}}</div>
    <div class="checkbox-item" v-for="option in options" :key="option.value" @click="doSelect(option)">
      <input type="checkbox" :id="checkboxName + option.value" :name="checkboxName" v-model="currentValue" :disabled="option.disabled" :value="option.value"/>
      <span class="item-bar">
        <span class="input-span">{{option.text}}</span>
        <span class="input-icon">
          <Icon name="tick" class="tick-icon"></Icon>
        </span>
      </span>
    </div>
  </div>
</template>
<script>
export default {
  name: 'CheckboxGroup',
  props: {
    // 单选组标题
    title: String,
    /**
     * 单选项目数组
     * 数组中对象示例:{ value: ‘01’, text: '男', disabled:false}
     *  value: 值
     *  text: 显示的文字
     *  disabled: 是否可用
     **/
    options: {
      type: Array,
      required: true
    },
    // 当前选中值
    value: {
      type: Array,
      default: () => []
    }
  },
  data () {
    return {
      currentValue: this.value,
      checkboxName: 'checkboxgroup-' + Math.random().toString(36).substring(3, 6)
    }
  },
  watch: {
    value (val) {
      this.currentValue = [...val]
    }
  },
  methods: {
    doSelect (option) {
      if (option.disabled) return
      let value = option.value
      let idx = this.currentValue.indexOf(value)
      if (idx === -1) {
        this.currentValue.push(value)
      } else {
        this.currentValue.splice(idx, 1)
      }
      this.currentValue.sort()
      this.$emit('input', this.currentValue)
      this.$emit('change', this.currentValue)
    }
  }
}
</script>
<style lang="scss" scoped>
.checkbox-group{
  font-size: 36px;
  line-height: 90px;
  .checkbox-title{
    padding: 0 40px;
    color: #333;
    background-color: #F5F5F5;
  }
  .checkbox-item{
    position: relative;
    padding: 0 40px;
    background-color: #FFF;
    input {
      position: absolute;
      top: 50%;
      left: -100000px;
      width: 1em;
      height: 1em;
      transform: translate(0, -50%);
      font-size: inherit;
      &:checked + .item-bar {
        .input-icon{
          opacity: 1;
        }
      }
      &:disabled + .item-bar {
        .input-span {
          color: #999;
        }
        .input-icon{
          color: #A2A2A2;
        }
      }
    }
    .item-bar{
      display: flex;
      align-items: center;
      justify-content: space-between;
      .input-icon{
        opacity: 0;
        color: #00AAFF;
      }
    }
  }
}
</style>

「欢迎在评论区讨论」

希望看完的朋友可以给个赞,鼓励一下