扩展uview复选组件库支持自定义图片+自定义内容

简介: 扩展uview复选组件库支持自定义图片+自定义内容

uView 是一套基于UniApp 的前端 UI 框架,它提供了丰富的组件库,用于快速开发移动端和微信小程序等应用。

基本使用

在 uView 中,复选组件通常用于让用户从一组选项中选择多个项目。这些组件可能以 Checkbox Group(复选框组)和 Checkbox(复选框)的形式出现。

把组件拖过来,什么都不需要改,即可生成复选组件。

<template>
  <view class="container container329152">
    <u-form-item class="diygw-col-24" label="复选" prop="checkbox">
      <u-checkbox-group class="flex flex-wrap diygw-col-24 justify-between" wrapClass=" justify-between" v-model="checkbox">
        <u-checkbox v-for="(checkboxitem, checkboxindex) in checkboxDatas" :key="checkboxindex" :name="checkboxitem.value">
          {{ checkboxitem.label }}
        </u-checkbox>
      </u-checkbox-group>
    </u-form-item>
    <view class="clearfix"></view>
  </view>
</template>
 
<script>
  export default {
    data() {
      return {
        //用户全局信息
        userInfo: {},
        //页面传参
        globalOption: {},
        //自定义全局变量
        globalData: {},
        checkboxDatas: [
          { value: '1', label: '选项一' },
          { value: '2', label: '选项二' },
          { value: '3', label: '选项三' }
        ],
        checkbox: ['1', '2']
      };
    },
    onShow() {
      this.setCurrentPage(this);
    },
    onLoad(option) {
      this.setCurrentPage(this);
      if (option) {
        this.setData({
          globalOption: this.getOption(option)
        });
      }
 
      this.init();
    },
    methods: {
      async init() {}
    }
  };
</script>
 
<style lang="scss" scoped>
  .container329152 {
  }
</style>


自定义图片

开启自定义图标,分别设置默认图片及选中图片


自定义内容

可以先外层造 好自己想要的FLEX布局的内容,开启自定义模板,把FLEX内容往里一拖,重新生成源码即可。


扩展源码

<template>
  <view
      class="flex flex-wrap"
      :class="[wrapClass]"
  >
    <slot></slot>
  </view>
</template>
 
<script>
  import props from './props.js';
  import Emitter from "../../libs/util/emitter.js";
  /**
   * checkboxGroup 复选框组
   * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
   * @tutorial https://www.uviewui.com/components/checkbox.html
   * @property {String}     name      标识符 
   * @property {Array}      value     绑定的值
   * @property {String}     shape     形状,circle-圆形,square-方形 (默认 'square' )
   * @property {Boolean}      disabled    是否禁用全部checkbox (默认 false )
   * @property {String}     activeColor   选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' )
   * @property {String}     inactiveColor 未选中的颜色 (默认 '#c8c9cc' )
   * @property {String | Number}  size      整个组件的尺寸 单位px (默认 18 )
   * @property {String}     placement   布局方式,row-横向,column-纵向 (默认 'row' )
   * @property {String | Number}  labelSize   label的字体大小,px单位  (默认 14 )
   * @property {String}     labelColor    label的字体颜色 (默认 '#303133' )
   * @property {Boolean}      labelDisabled 是否禁止点击文本操作 (默认 false )
   * @property {String}     iconColor   图标颜色 (默认 '#ffffff' )
   * @property {String | Number}  iconSize    图标的大小,单位px (默认 12 )
   * @property {String}     iconPlacement 勾选图标的对齐方式,left-左边,right-右边  (默认 'left' )
   * @property {Boolean}      borderBottom  placement为row时,是否显示下边框 (默认 false )
   * @event {Function}  change  任一个checkbox状态发生变化时触发,回调为一个对象
   * @event {Function}  input 修改通过v-model绑定的值时触发,回调为一个对象
   * @example <u-checkbox-group></u-checkbox-group>
   */
  export default {
    name: 'u-checkbox-group',
    mixins: [Emitter,props],
    computed: {
      // 这里computed的变量,都是子组件u-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
      // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-checkbox-group)
      // 拉取父组件新的变化后的参数
      parentData() {
        return [this.value, this.modelValue,this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape,
          this.iconSize, this.borderBottom, this.placement
        ]
      },
      bemClass() {
        // this.bem为一个computed变量,在mixin中
        return this.bem('checkbox-group', ['placement'])
      },
    },
    watch: {
      // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
      parentData() {
        if (this.children.length) {
          this.children.map(child => {
            // 判断子组件(u-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
            typeof(child.init) === 'function' && child.init()
          })
        }
      },
    },
    data() {
      return {
 
      }
    },
    created() {
      this.children = []
    },
    methods: {
      // 将其他的checkbox设置为未选中的状态
      unCheckedOther(childInstance) {
        const values = []
        this.children.map(child => {
          // 将被选中的checkbox,放到数组中返回
          if (child.isChecked) {
            values.push(child.name)
          }
        })
        this.$nextTick(()=>{
          // 发出事件
          this.$emit('change', values)
        })
        // 修改通过v-model绑定的值
        this.$emit('input', values)
        this.$emit("update:modelValue", values);
        // 由于头条小程序执行迟钝,故需要用几十毫秒的延时
        setTimeout(() => {
          // 将当前的值发送到 u-form-item 进行校验
          this.dispatch("u-form-item", "onFieldChange", values);
        }, 60);
      },
    }
  }
</script>
 
<style lang="scss" scoped>
  @import "../../libs/css/style.components.scss";
  .u-checkbox-group {
 
    &--row {
      @include vue-flex;
      flex-wrap: wrap;
    }
 
    &--column {
      @include vue-flex(column);
      flex-wrap: wrap;
    }
  }
</style>


 let checkbox = {
  name: '',
  shape: '',
  size: '',
  checkbox: false,
  disabled: '',
  activeColor: '',
  inactiveColor: '',
  iconSize: '',
  iconColor: '',
  label: '',
  labelSize: '',
  labelColor: '',
  labelDisabled: ''
 }
 export default {
  props: {
    // checkbox的名称
    name: {
      type: [String, Number, Boolean],
      default: checkbox.name
    },
    // 形状,square为方形,circle为圆型
    shape: {
      type: String,
      default: checkbox.shape
    },
    // 整体的大小
    size: {
      type: [String, Number],
      default: checkbox.size
    },
    // 每个组件都有的父组件传递的样式,可以为字符串或者对象形式
    customStyle: {
      type: [Object, String],
      default: () => ({})
    },
    customClass: {
      type: String,
      default: ''
    },
    // 是否默认选中
    checked: {
      type: Boolean,
      default: checkbox.checked
    },
    // 是否禁用
    disabled: {
      type: [String, Boolean],
      default: checkbox.disabled
    },
    // 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
    activeColor: {
      type: String,
      default: checkbox.activeColor
    },
    // 未选中的颜色
    inactiveColor: {
      type: String,
      default: checkbox.inactiveColor
    },
    // 图标的大小,单位px
    iconSize: {
      type: [String, Number],
      default: checkbox.iconSize
    },
    // 图标颜色
    iconColor: {
      type: String,
      default: checkbox.iconColor
    },
    // label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
    label: {
      type: [String, Number],
      default: checkbox.label
    },
    // label的字体大小,px单位
    labelSize: {
      type: [String, Number],
      default: checkbox.labelSize
    },
    // label的颜色
    labelColor: {
      type: String,
      default: checkbox.labelColor
    },
    // 是否禁止点击提示语选中复选框
    labelDisabled: {
      type: [String, Boolean],
      default: checkbox.labelDisabled
    },
    activeImg:{
      type: String,
      default: ''
    },
    img:{
      type: String,
      default: ''
    }
  }
 }
<template>
  <view
      class="u-checkbox"
      :style="[checkboxStyle]"
      @tap.stop="wrapperClickHandler"
      :class="[`u-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'u-border-bottom']"
  >
    <view
        class="u-checkbox__image-wrap"
        @tap.stop="iconClickHandler"
        :class="iconClasses"
      v-if="activeImg&&img" 
    >
      <image class="u-checkbox__image-wrap_img" :style="{width:$u.addUnit(elIconSize*2),height:$u.addUnit(elIconSize*2)}" :src="isChecked?activeImg:img"></image>
    </view>
    <view
        v-else
        class="u-checkbox__icon-wrap"
        @tap.stop="iconClickHandler"
        :class="iconClasses"
        :style="[iconWrapStyle]"
    >
      <slot name="icon">
        <u-icon
            class="u-checkbox__icon-wrap__icon"
            name="checkbox-mark"
            :size="elIconSize"
            :color="elIconColor"
        />
      </slot>
    </view>
    <view
        @tap.stop="labelClickHandler"
      class="u-checkbox__label"
        :style="{
        color: elDisabled ? elInactiveColor : elLabelColor,
        fontSize: elLabelSize,
        lineHeight: elLabelSize
      }"
    ><slot /></view>
  </view>
</template>
 
<script>
  import props from './props.js';
  /**
   * checkbox  复选框
   * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
   * @tutorial https://uviewui.com/components/checkbox.html
   * @property {String | Number | Boolean}  name      checkbox组件的标示符
   * @property {String}           shape     形状,square为方形,circle为圆型
   * @property {String | Number}        size      整体的大小
   * @property {Boolean}            checked     是否默认选中
   * @property {String | Boolean}       disabled    是否禁用
   * @property {String}           activeColor   选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
   * @property {String}           inactiveColor 未选中的颜色
   * @property {String | Number}        iconSize    图标的大小,单位px
   * @property {String}           iconColor   图标颜色
   * @property {String | Number}        label     label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
   * @property {String}           labelColor    label的颜色
   * @property {String | Number}        labelSize   label的字体大小,px单位
   * @property {String | Boolean}       labelDisabled 是否禁止点击提示语选中复选框
   * @property {Object}           customStyle   定义需要用到的外部样式
   * 
   * @event {Function}  change  任一个checkbox状态发生变化时触发,回调为一个对象
   * @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
   */
  export default {
    name: "u-checkbox",
    mixins: [props],
    data() {
      return {
        isChecked: false,
        // 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式
        // 故只能使用如此方法
        parentData: {
          iconSize: 12,
          labelDisabled: null,
          disabled: null,
          shape: 'square',
          activeColor: null,
          inactiveColor: null,
          size: 18,
          value: null,
          iconColor: null,
          placement: 'row',
          borderBottom: false,
          iconPlacement: 'left'
        }
      }
    },
    computed: {
      // 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置
      elDisabled() {
        return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
      },
      // 是否禁用label点击
      elLabelDisabled() {
        return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled :
          false;
      },
      // 组件尺寸,对应size的值,默认值为21px
      elSize() {
        return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21);
      },
      // 组件的勾选图标的尺寸,默认12px
      elIconSize() {
        return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12);
      },
      // 组件选中激活时的颜色
      elActiveColor() {
        return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff');
      },
      // 组件选未中激活时的颜色
      elInactiveColor() {
        return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor :
          '#c8c9cc');
      },
      // label的颜色
      elLabelColor() {
        return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266')
      },
      // 组件的形状
      elShape() {
        return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle');
      },
      // label大小
      elLabelSize() {
        let labelSize = this.labelSize ? this.labelSize : this.parentData.labelSize
        if(!labelSize){
          return 'inherit'
        }
        return uni.$u.addUnit(labelSize+'px')
      },
      elIconColor() {
        const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor :
          '#ffffff');
        // 图标的颜色
        if (this.elDisabled) {
          // disabled状态下,已勾选的checkbox图标改为elInactiveColor
          return this.isChecked ? this.elInactiveColor : 'transparent'
        } else {
          return this.isChecked ? iconColor : 'transparent'
        }
      },
      iconClasses() {
        let classes = []
        // 组件的形状
        classes.push('u-checkbox__icon-wrap--' + this.elShape)
        if (this.elDisabled) {
          classes.push('u-checkbox__icon-wrap--disabled')
        }
        if (this.isChecked && this.elDisabled) {
          classes.push('u-checkbox__icon-wrap--disabled--checked')
        }
        // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
        // #ifdef MP-ALIPAY || MP-TOUTIAO
        classes = classes.join(' ')
        // #endif
        return classes
      },
      iconWrapStyle() {
        // checkbox的整体样式
        const style = {}
        style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff'
        style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor
        style.width = uni.$u.addUnit(this.elSize+'px')
        style.height = uni.$u.addUnit(this.elSize+'px')
        // 如果是图标在右边的话,移除它的右边距
        if (this.parentData.iconPlacement === 'right') {
          style.marginRight = 0
        }
        return style
      },
      checkboxStyle() {
        const style = {}
        if (this.parentData.borderBottom && this.parentData.placement === 'row') {
          uni.$u.error('检测到您将borderBottom设置为true,需要同时将u-checkbox-group的placement设置为column才有效')
        }
        // 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔
        if (this.parentData.borderBottom && this.parentData.placement === 'column') {
          style.paddingBottom = '8px'
        }
        return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
      }
    },
    mounted() {
      this.init()
    },
    methods: {
      init() {
        // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
        this.updateParentData()
        if (!this.parent) {
          uni.$u.error('u-checkbox必须搭配u-checkbox-group组件使用')
        }
        // 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
        if (this.checked) {
          this.isChecked = true
        } else if (uni.$u.test.array(this.parentData.value)) {
          // 查找数组是是否存在this.name元素值
          this.isChecked = this.parentData.value.some(item => {
            return item === this.name
          })
        }
      },
      updateParentData() {
        this.getParentData('u-checkbox-group')
      },
      // 横向两端排列时,点击组件即可触发选中事件
      wrapperClickHandler(e) {
        this.parentData.iconPlacement === 'right' && this.iconClickHandler(e)
      },
      // 点击图标
      iconClickHandler(e) {
        this.preventEvent(e)
        // 如果整体被禁用,不允许被点击
        if (!this.elDisabled) {
          this.setRadioCheckedStatus()
        }
      },
      // 点击label
      labelClickHandler(e) {
        this.preventEvent(e)
        // 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态
        if (!this.elLabelDisabled && !this.elDisabled) {
          this.setRadioCheckedStatus()
        }
      },
      emitEvent() {
        this.$emit('change', this.isChecked)
        // 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时
        // this.$nextTick(() => {
        //  uni.$u.formValidate(this, 'change')
        // })
      },
      // 改变组件选中状态
      // 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有u-checkbox实例
      // 将本组件外的其他u-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态
      setRadioCheckedStatus() {
        // 将本组件标记为与原来相反的状态
        this.isChecked = !this.isChecked
        this.emitEvent()
        typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this)
      }
    },
    watch:{
      checked(){
        this.isChecked = this.checked
      }
    }
  }
</script>
 
<style lang="scss" scoped>
  @import "../../libs/css/style.components.scss";
  $u-checkbox-icon-wrap-margin-right:0px !default;
  $u-checkbox-icon-wrap-font-size:6px !default;
  $u-checkbox-icon-wrap-border-width:1px !default;
  $u-checkbox-icon-wrap-border-color:#c8c9cc !default;
  $u-checkbox-icon-wrap-icon-line-height:0 !default;
  $u-checkbox-icon-wrap-circle-border-radius:100% !default;
  $u-checkbox-icon-wrap-square-border-radius:3px !default;
  $u-checkbox-icon-wrap-checked-color:#fff !default;
  $u-checkbox-icon-wrap-checked-background-color:red !default;
  $u-checkbox-icon-wrap-checked-border-color:#2979ff !default;
  $u-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default;
  $u-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default;
  $u-checkbox-label-margin-left:5px !default;
  $u-checkbox-label-margin-right:12px !default;
  $u-checkbox-label-color:$u-content-color !default;
  $u-checkbox-label-font-size:15px !default;
  $u-checkbox-label-disabled-color:#c8c9cc !default;
 
  .u-checkbox {
    /* #ifndef APP-NVUE */
    @include vue-flex(row);
    /* #endif */
    overflow: hidden;
    flex-direction: row;
    align-items: center;
    line-height: 1.8;
 
    &-label--left {
      flex-direction: row
    }
 
    &-label--right {
      flex-direction: row-reverse;
      justify-content: space-between
    }
 
      &__image-wrap{
      @include vue-flex;
      flex-shrink: 0;
      align-items: center;
      justify-content: center;
      color: transparent;
      text-align: center;
    }
  
    &__icon-wrap {
      /* #ifndef APP-NVUE */
      box-sizing: border-box;
      // nvue下,border-color过渡有问题
      transition-property: border-color, background-color, color;
      transition-duration: 0.2s;
      /* #endif */
      color: $u-content-color;
      @include vue-flex;
      flex-shrink: 0;
      align-items: center;
      justify-content: center;
      color: transparent;
      text-align: center;
      margin-right: $u-checkbox-icon-wrap-margin-right;
 
      font-size: $u-checkbox-icon-wrap-font-size;
      border-width: $u-checkbox-icon-wrap-border-width;
      border-color: $u-checkbox-icon-wrap-border-color;
      border-style: solid;
 
      /* #ifdef MP-TOUTIAO */
      // 头条小程序兼容性问题,需要设置行高为0,否则图标偏下
      &__icon {
        line-height: $u-checkbox-icon-wrap-icon-line-height;
      }
 
      /* #endif */
 
      &--circle {
        border-radius: $u-checkbox-icon-wrap-circle-border-radius;
      }
 
      &--square {
        border-radius: $u-checkbox-icon-wrap-square-border-radius;
      }
 
      &--checked {
        color: $u-checkbox-icon-wrap-checked-color;
        background-color: $u-checkbox-icon-wrap-checked-background-color;
        border-color: $u-checkbox-icon-wrap-checked-border-color;
      }
 
      &--disabled {
        background-color: $u-checkbox-icon-wrap-disabled-background-color !important;
      }
 
      &--disabled--checked {
        color: $u-checkbox-icon-wrap-disabled-checked-color !important;
      }
    }
 
    &__label {
      flex:1;
      /* #ifndef APP-NVUE */
      word-wrap: break-word;
      /* #endif */
      margin-left: $u-checkbox-label-margin-left;
      margin-right: $u-checkbox-label-margin-right;
      color: $u-checkbox-label-color;
      font-size: $u-checkbox-label-font-size;
 
      &--disabled {
        color: $u-checkbox-label-disabled-color;
      }
    }
  }
</style>
目录
相关文章
|
6月前
|
前端开发 JavaScript
使用JavaScript实现复杂功能:构建一个自定义的拖拽功能
使用JavaScript实现复杂功能:构建一个自定义的拖拽功能
|
16天前
|
UED 开发者 容器
鸿蒙next版开发:ArkTS组件通用属性(位置设置)
在HarmonyOS next中,ArkTS提供了align、direction、position、markAnchor、offset和alignRules等通用属性,用于精确控制组件在用户界面中的位置和布局。本文详细解读了这些属性,并提供了示例代码进行说明。通过这些属性,开发者可以实现精确布局、动态界面调整和提升用户体验。
58 6
|
16天前
|
UED 开发者
鸿蒙next版开发:ArkTS组件通用属性(图片边框设置)
在HarmonyOS 5.0中,ArkTS提供了灵活的图片边框设置属性,使开发者可以为应用中的图片组件添加各种边框效果,提升视觉效果和用户体验。本文详细解读了ArkTS中图片边框设置的通用属性,并提供了示例代码。通过设置`borderImage`属性,可以控制边框的图源、切割宽度、边框宽度、延伸距离、平铺模式和是否填充。示例代码展示了如何使用这些属性来创建具有不同边框效果的图片组件。图片边框设置在美化界面、区分内容和增强交互方面有重要作用。
41 5
|
4月前
|
前端开发 JavaScript 索引
uniapp的u-album组件自定义删除功能
这样,你就可以在u-album组件中实现自定义的删除功能了。需要注意的是,这个删除操作只是在前端删除了图片项,并没有在后端删除对应的图片文件,如果你需要在后端也删除对应的图片文件,你还需要在删除操作后发送一个请求到后端,让后端删除对应的图片文件。
118 0
|
4月前
|
小程序 JavaScript 前端开发
【微信小程序-原生开发】实用教程06-轮播图、分类页签 tab 、成员列表(含Tdesign升级,切换调试基础库,设置全局样式,配置组件按需注入,添加图片素材,wx:for,生命周期 onLoad)
【微信小程序-原生开发】实用教程06-轮播图、分类页签 tab 、成员列表(含Tdesign升级,切换调试基础库,设置全局样式,配置组件按需注入,添加图片素材,wx:for,生命周期 onLoad)
155 0
|
6月前
|
JavaScript 前端开发 API
【每周一个小技巧】如何自定义客服、生活号组件的样式
【每周一个小技巧】如何自定义客服、生活号组件的样式
70 8
|
6月前
Qt表格中的自定义编辑组件---------------自定义代理QStyledItemDelegate
Qt表格中的自定义编辑组件---------------自定义代理QStyledItemDelegate
84 5
|
6月前
|
移动开发 JavaScript 小程序
uniapp中组件库丰富的Switch 开关选择器使用方法
uniapp中组件库丰富的Switch 开关选择器使用方法
437 1
|
JavaScript
fastadmin 自定义 按钮 动态切换数据 TAB切换
fastadmin 自定义 按钮 动态切换数据 TAB切换
285 0
antd组件库封装74-subMenu下拉菜单编码-完美组件2
antd组件库封装74-subMenu下拉菜单编码-完美组件2
102 0
antd组件库封装74-subMenu下拉菜单编码-完美组件2
下一篇
无影云桌面