<template> 
 | 
  <view class="tn-checkbox-class tn-checkbox" :style="[checkboxStyle]"> 
 | 
    <view 
 | 
      class="tn-checkbox__icon-wrap" 
 | 
      :class="[iconClass]" 
 | 
      :style="[iconStyle]" 
 | 
      @tap="toggle" 
 | 
    > 
 | 
      <view class="tn-checkbox__icon-wrap__icon" :class="[`tn-icon-${iconName}`]"></view> 
 | 
    </view> 
 | 
     
 | 
    <view 
 | 
      class="tn-checkbox__label" 
 | 
      :class="[labelClass]" 
 | 
      :style="{ 
 | 
        fontSize: labelSize ? labelSize + 'rpx' : '' 
 | 
      }" 
 | 
      @tap="onClickLabel" 
 | 
    > 
 | 
      <slot></slot> 
 | 
    </view> 
 | 
  </view> 
 | 
</template> 
 | 
  
 | 
<script> 
 | 
  export default { 
 | 
    name: 'tn-checkbox', 
 | 
    props: { 
 | 
      // checkbox名称 
 | 
      name: { 
 | 
        type: [String, Number], 
 | 
        default: '' 
 | 
      }, 
 | 
      // 是否为选中状态 
 | 
      value: { 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      // 禁用选择 
 | 
      disabled: { 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      // 禁用点击标签进行选择 
 | 
      disabledLabel: { 
 | 
        type: Boolean, 
 | 
        default: false 
 | 
      }, 
 | 
      // 选择框的形状 square 方形 circle 圆形 
 | 
      shape: { 
 | 
        type: String, 
 | 
        default: '' 
 | 
      }, 
 | 
      // 选中时的颜色 
 | 
      activeColor: { 
 | 
        type: String, 
 | 
        default: '' 
 | 
      }, 
 | 
      // 组件大小 
 | 
      size: { 
 | 
        type: Number, 
 | 
        default: 0 
 | 
      }, 
 | 
      // 图标名称 
 | 
      iconName: { 
 | 
        type: String, 
 | 
        default: 'success' 
 | 
      }, 
 | 
      // 图标大小 
 | 
      iconSize: { 
 | 
        type: Number, 
 | 
        default: 0 
 | 
      }, 
 | 
      // label的字体大小 
 | 
      labelSize: { 
 | 
        type: Number, 
 | 
        default: 0 
 | 
      } 
 | 
    }, 
 | 
    computed: { 
 | 
      // 是否禁用选中,父组件的禁用会覆盖当前的禁用状态 
 | 
      isDisabled() { 
 | 
        return this.disabled ? this.disabled : (this.parent ? this.parentData.disabled : false) 
 | 
      }, 
 | 
      // 是否禁用点击label选中,父组件的禁用会覆盖当前的禁用状态 
 | 
      isDisabledLabel() { 
 | 
        return this.disabledLabel ? this.disabledLabel : (this.parent ? this.parentData.disabledLabel : false) 
 | 
      }, 
 | 
      // 尺寸 
 | 
      checkboxSize() { 
 | 
        return this.size ? this.size : (this.parent ? this.parentData.size : 34) 
 | 
      }, 
 | 
      // 激活时的颜色 
 | 
      elAvtiveColor() { 
 | 
        return this.activeColor ? this.activeColor : (this.parent ? this.parentData.activeColor : '#01BEFF') 
 | 
      }, 
 | 
      // 形状 
 | 
      elShape() { 
 | 
        return this.shape ? this.shape : (this.parent ? this.parentData.shape : 'square') 
 | 
      }, 
 | 
      iconClass() { 
 | 
        let clazz = '' 
 | 
        clazz += (' tn-checkbox__icon-wrap--' + this.elShape) 
 | 
         
 | 
        if (this.checkValue) clazz += ' tn-checkbox__icon-wrap--checked' 
 | 
        if (this.isDisabled) clazz += ' tn-checkbox__icon-wrap--disabled' 
 | 
        if (this.value && this.isDisabled) clazz += ' tn-checkbox__icon-wrap--disabled--checked' 
 | 
         
 | 
        return clazz 
 | 
      }, 
 | 
      iconStyle() { 
 | 
        let style = {} 
 | 
        // 判断是否用户手动禁用和传递的值 
 | 
        if (this.elAvtiveColor && this.checkValue && !this.isDisabled) { 
 | 
          style.borderColor = this.elAvtiveColor 
 | 
          style.backgroundColor = this.elAvtiveColor 
 | 
        } 
 | 
         
 | 
        // checkbox内部的勾选图标,如果选中状态,为白色,否则为透明色即可 
 | 
        style.color = this.checkValue ? '#FFFFFF' : 'transparent' 
 | 
         
 | 
        style.width = this.checkboxSize + 'rpx' 
 | 
        style.height = style.width 
 | 
         
 | 
        style.fontSize = (this.iconSize ? this.iconSize : (this.parent ? this.parentData.iconSize : 20)) + 'rpx' 
 | 
         
 | 
        return style 
 | 
      }, 
 | 
      checkboxStyle() { 
 | 
        let style = {} 
 | 
        if (this.parent && this.parentData.width) { 
 | 
          // #ifdef MP 
 | 
          // 各家小程序因为它们特殊的编译结构,使用float布局 
 | 
          style.float = 'left'; 
 | 
          // #endif 
 | 
          // #ifndef MP 
 | 
          // H5和APP使用flex布局 
 | 
          style.flex = `0 0 ${this.parentData.width}`; 
 | 
          // #endif 
 | 
        } 
 | 
        if(this.parent && this.parentData.wrap) { 
 | 
            style.width = '100%'; 
 | 
            // #ifndef MP 
 | 
            // H5和APP使用flex布局,将宽度设置100%,即可自动换行 
 | 
            style.flex = '0 0 100%'; 
 | 
            // #endif 
 | 
        } 
 | 
         
 | 
        return style 
 | 
      }, 
 | 
      labelClass() { 
 | 
        let clazz = '' 
 | 
        if (this.isDisabled) { 
 | 
          clazz += ' tn-checkbox__label--disabled' 
 | 
        } 
 | 
        return clazz 
 | 
      } 
 | 
    }, 
 | 
    data() { 
 | 
      return { 
 | 
        // 当前checkbox的value值 
 | 
        checkValue: false, 
 | 
        parentData: { 
 | 
          value: null, 
 | 
          max: null, 
 | 
          disabled: null, 
 | 
          disabledLabel: null, 
 | 
          shape: null, 
 | 
          activeColor: null, 
 | 
          size: null, 
 | 
          width: null, 
 | 
          wrap: null, 
 | 
          iconSize: null 
 | 
        } 
 | 
      } 
 | 
    }, 
 | 
    watch: { 
 | 
      value(val) { 
 | 
        this.checkValue = val 
 | 
      } 
 | 
    }, 
 | 
    created() { 
 | 
      // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环应用 
 | 
      // this.parent = this.$t.$parent.call(this, 'tn-checkbox-group') 
 | 
      // // 如果存在u-checkbox-group,将本组件的this塞进父组件的children中 
 | 
      // this.parent && this.parent.children.push(this) 
 | 
      // // 初始化父组件的value值 
 | 
      // this.parent && this.parent.emitEvent() 
 | 
      this.updateParentData() 
 | 
      this.parent && this.parent.children.push(this) 
 | 
    }, 
 | 
    methods: { 
 | 
      updateCheckValue() { 
 | 
        // 更新当前checkbox的选中状态 
 | 
        this.checkValue = (this.parent && this.parentData.value.includes(this.name)) || this.value === true 
 | 
        if (this.parent) { 
 | 
          if (this.value && !this.parentData.value.includes(this.name)) { 
 | 
            this.parentData.value.push(this.name) 
 | 
            this.parent.initValue(this.parentData.value) 
 | 
          } 
 | 
        } 
 | 
      }, 
 | 
      updateParentData() { 
 | 
        this.getParentData('tn-checkbox-group') 
 | 
        this.updateCheckValue() 
 | 
      }, 
 | 
      onClickLabel() { 
 | 
        if (!this.isDisabled && !this.isDisabledLabel) { 
 | 
          this.setValue() 
 | 
        } 
 | 
      }, 
 | 
      toggle() { 
 | 
        if (!this.isDisabled) { 
 | 
          this.setValue() 
 | 
        } 
 | 
      }, 
 | 
      emitEvent() { 
 | 
        this.$emit('change', { 
 | 
          name: this.name, 
 | 
          value: !this.checkValue 
 | 
        }) 
 | 
        if (this.parent) { 
 | 
          this.checkValue = !this.checkValue 
 | 
          // 执行父组件tn-checkbox-group的事件方法 
 | 
          // 等待下一个周期再执行,因为this.$emit('input')作用于父组件,再反馈到子组件内部,需要时间 
 | 
          setTimeout(() => { 
 | 
            if(this.parent.emitEvent) this.parent.emitEvent(); 
 | 
          }, 80) 
 | 
        } 
 | 
      }, 
 | 
      // 设置input的值,通过v-modal绑定组件的值 
 | 
      setValue() { 
 | 
        // 判断是否为可选项组 
 | 
        if (this.parent) { 
 | 
          // 反转状态 
 | 
          if (this.checkValue === true) { 
 | 
            this.emitEvent() 
 | 
            // this.$emit('input', !this.checkValue) 
 | 
          } else { 
 | 
            // 超出最大可选项,弹出提示 
 | 
            if (this.parentData.value.length >= this.parentData.max) { 
 | 
              return this.$t.message.toast(`最多可选${this.parent.max}项`) 
 | 
            } 
 | 
            // 如果原来为未选中状态,需要选中的数量少于父组件中设置的max值,才可以选中 
 | 
            this.emitEvent(); 
 | 
            // this.$emit('input', !this.checkValue); 
 | 
          } 
 | 
        } else { 
 | 
          // 只有一个可选项 
 | 
          this.emitEvent() 
 | 
          this.$emit('input', !this.checkValue) 
 | 
        } 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
</script> 
 | 
  
 | 
<style lang="scss" scoped> 
 | 
   
 | 
  .tn-checkbox { 
 | 
    /* #ifndef APP-NVUE */ 
 | 
    display: inline-flex; 
 | 
    /* #endif */ 
 | 
    align-items: center; 
 | 
    overflow: hidden; 
 | 
    user-select: none; 
 | 
    line-height: 1.8; 
 | 
     
 | 
    &__icon-wrap { 
 | 
      color: $tn-font-color; 
 | 
      flex: none; 
 | 
      display: flex; 
 | 
      flex-direction: row; 
 | 
      align-items: center; 
 | 
      justify-content: center; 
 | 
      box-sizing: border-box; 
 | 
      width: 42rpx; 
 | 
      height: 42rpx; 
 | 
      color: transparent; 
 | 
      text-align: center; 
 | 
      transition-property: color, border-color, background-color; 
 | 
      border: 1px solid $tn-font-sub-color; 
 | 
      transition-duration: 0.2s; 
 | 
       
 | 
      /* #ifdef MP-TOUTIAO */ 
 | 
      // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下 
 | 
      &__icon { 
 | 
          line-height: 0; 
 | 
      } 
 | 
      /* #endif */ 
 | 
       
 | 
      &--circle { 
 | 
        border-radius: 100%; 
 | 
      } 
 | 
       
 | 
      &--square { 
 | 
        border-radius: 6rpx; 
 | 
      } 
 | 
       
 | 
      &--checked { 
 | 
        color: #FFFFFF; 
 | 
        background-color: $tn-main-color; 
 | 
        border-color: $tn-main-color; 
 | 
      } 
 | 
       
 | 
      &--disabled { 
 | 
        background-color: $tn-font-holder-color; 
 | 
        border-color: $tn-font-sub-color; 
 | 
      } 
 | 
       
 | 
      &--disabled--checked { 
 | 
        color: $tn-font-sub-color !important; 
 | 
      } 
 | 
    } 
 | 
     
 | 
    &__label { 
 | 
      word-wrap: break-word; 
 | 
      margin-left: 10rpx; 
 | 
      margin-right: 24rpx; 
 | 
      color: $tn-font-color; 
 | 
      font-size: 30rpx; 
 | 
       
 | 
      &--disabled { 
 | 
        color: $tn-font-sub-color; 
 | 
      } 
 | 
    } 
 | 
  } 
 | 
</style> 
 |