:Checkbox组件

Posted anyRTC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:Checkbox组件相关的知识,希望对你有一定的参考价值。

大家好今天的内容是基于vue3实现自己的组件库系列第二章,本文默认你会安装和创建vue3项目,如果不会请参考vue官网

Checkbox.vue Template

<template>
    <div :class='["v-checkbox",  border , 
     disabled: proxyDisabled || disabled || computedDisabled , 
     medium: border && (size || proxySize) === "medium" ,
     small: border && (size || proxySize) === "small" ,
     mini: border && (size || proxySize) === "mini" ,
     "v-radio-checked": computedChecked && !computedDisabled ]' 
    @click.stop='handleChecked'>
        <input type="checkbox" :checked='computedChecked' :disabled='disabled' :name='name || modelValue || proxyValue' :value='label'>
        <span :class='["v-radio-input",  checked: computedChecked ,  indeterminate ]'></span>
        <span :class='["v-radio-label",  active: computedChecked ]'>
            <slot></slot>
        </span>
    </div>
</template>

Checkbox.vue Script

<script>
import  inject, computed  from 'vue';
import VairCheckout from '@/types/checkout';
export default 
    name: 'checkbox',
    props: VairCheckout,
    setup (props, ctx) 
        const proxyValue = inject('proxyValue');
        const proxyDisabled = inject('proxyDisabled');
        const proxySize = inject('proxySize');
        const proxyMin = inject('proxyMin');
        const proxyMax = inject('proxyMax');
        const update = inject('update');

        const handleChecked = () => 
            if (!props.disabled && !computedDisabled.value) 
                if (proxyValue) 
                    ctx.emit('change', props.label);
                    update(props.label);
                 else 
                    const value = props.modelValue? false : true;
                    ctx.emit('update:modelValue', value);
                    ctx.emit('change', value);
                
            
        ;

        const computedDisabled = computed(() => 
            var bool = false;
            if (proxyMax || proxyMin) 
                if (proxyMax && proxyValue.value.length >= proxyMax.value) 
                    if (!computedChecked.value) 
                        bool = true;
                    
                 else if (proxyMin && proxyValue.value.length <= proxyMin.value) 
                    if (computedChecked.value) 
                        bool = true;
                    
                
            
            return bool;
        );

        const computedChecked = computed(() => 
            if (proxyValue)  // 如果是被 checkbox-group 组件包裹着的话就判断数组中有没有符合的值
                return proxyValue.value.find(item => item === props.label);
             else 
                return props.modelValue;
            
        );

        return 
            handleChecked,
            proxyDisabled,
            computedChecked,
            computedDisabled,
            proxyValue,
            proxySize
        
    

</script>

Checkbox.js

const VairCheckout = 
    modelValue: null, // 绑定值
    name: String, // 原生 name 属性
    label: [Number, String, Boolean], // Checkbox 的 value
    size: String, // Radio 的尺寸,仅在 border 为真时有效
    indeterminate:  // 设置 indeterminate 状态,只负责样式控制
        type: Boolean,
        default: () => 
            return false
        
    ,
    border:  // 是否显示边框
        type: Boolean,
        default: () => 
            return false
        
    ,
    disabled:  // 是否禁用
        type: Boolean,
        default: () => 
            return false
        
    ,
;

// Event
    // change (label)

export default VairCheckout;

Checkbox.vue Style

<style lang='less' scoped>
@import url('../../assets/css/animation.css');
.v-checkbox 
    display: flex;
    align-items: center;
    cursor: pointer;
    transition: .3s;
    margin-right: 30px;
    &:last-child 
        margin-right: 0;
    
    input 
        display: none;
    
    .v-radio-input 
        border: 1px solid#dcdfe6;
        width: 14px;
        height: 14px;
        position: relative;
        box-sizing: border-box;
        border-radius: 2px;
        transition: .3s;
        &:after 
            box-sizing: content-box;
            content: "";
            border: 1px solid #fff;
            border-left: 0;
            border-top: 0;
            height: 7px;
            left: 4px;
            position: absolute;
            top: 1px;
            transform: rotate(45deg) scaleY(0);
            width: 3px;
            transition: transform .15s ease-in .05s;
            transform-origin: center;
        
    
    .indeterminate 
        background-color: #409eff;
        border-color: #409eff;
        position: relative;
        &:after 
            content: "";
            position: absolute;
            display: block;
            background-color: #fff;
            height: 2px;
            transform: scale(.5);
            left: 0;
            right: 0;
            width: 10px;
            transition: width 0s;
            top: 4px;
        
    
    .v-radio-label 
        color: #606266;
        font-weight: 500;
        margin-left: 10px;
        font-size: 14px;
        transition: .3s;
        white-space: nowrap;
        user-select: none;
    
    .active 
        color: #409eff;
    
    .checked 
        background-color: #409eff;
        border-color: #409eff;
        &:after 
            transform: rotate(45deg) scaleY(1);
        
    
    &:hover 
        border-color: #409eff;
        .v-radio-label 
            color: #409eff;
        
        .v-radio-input 
            border-color: #409eff;
        
    

.border 
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    padding: 12px 14px;

.medium 
    padding: 10px 10px;

.small 
    padding: 8px 8px;

.mini 
    padding: 6px 6px;

.v-radio-checked 
    border-color: #409eff;

.disabled 
    border-color: #dcdfe6;
    .v-radio-input 
        background-color: #F5F7FA;
        border: 1px solid#dcdfe6;
    
    .v-radio-label 
        color: #c0c4cc;
    
    .active 
        color: #c0c4cc;
    
    .checked 
        background-color: #f2f6fc;
        border-color: #dcdfe6;
        &:after 
            transform: rotate(45deg) scaleY(1);
            border-color: #c0c4cc;
        
    
    &:hover 
        border-color: #dcdfe6;
        .v-radio-label 
            color: #c0c4cc;
        
        .v-radio-input 
            border-color: #c0c4cc;
        
    
    cursor: not-allowed;

</style>

Checkbox-group.vue Template

<template>
    <div class="v-radio-group">
        <slot></slot>
    </div>
</template>

Checkbox-group.vue Script

<script>
import  provide, ref, watchEffect  from 'vue';
export default 
    name: 'checkbox-group',
    props: 
        modelValue: Array, // 绑定值
        size: String, // 单选框组尺寸,仅对按钮形式的 Radio 或带有边框的 Radio 有效
        min: Number, // 可被勾选的 checkbox 的最小数量
        max: Number, // 可被勾选的 checkbox 的最大数量
        textColor:  // 按钮形式的 Radio 激活时的文本颜色
            type: String,
            default: () => 
                return '#FFFFFF';
            
        ,
        fill:  // 按钮形式的 Radio 激活时的填充色
            type: String,
            default: () => 
                return '#409EFF';
            
        ,
        disabled:  // 是否禁用
            type: Boolean,
            default: () => 
                return false
            
        ,
    ,
    setup (props, ctx) 
        const proxyValue = ref(props.modelValue);
        const proxyDisabled = ref(props.disabled);
        const proxyFill = ref(props.fill);
        const proxyTextColor = ref(props.textColor);
        const proxySize = ref(props.size);
        const proxyMin = ref(props.min);
        const proxyMax = ref(props.max);

        watchEffect(() => 
            if (!Array.isArray(props.modelValue)) 
                throw new TypeError(`v-model wants to receive an array, but received a $typeof props.modelValue`);
            
            proxySize.value = props.size;
            proxyTextColor.value = props.textColor;
            proxyFill.value = props.fill;
            proxyMin.value = props.min;
            proxyMax.value = props.max;
            proxyDisabled.value = props.disabled;
            proxyValue.value = props.modelValue;
        );

        const update = (value) => 
            const bool = props.modelValue.find(item => item === value);
            var list = [];
            if (bool) 
                props.modelValue.forEach(item => 
                    if (item !== value) 
                        list.push(item);
                    
                );
             else 
                list = [].concat(props.modelValue, [value]);
            
            ctx.emit('update:modelValue', list);
            ctx.emit('change', list);
        ;

        provide('proxyValue', proxyValue);
        provide('proxyFill', proxyFill);
        provide('proxyDisabled', proxyDisabled);
        provide('proxyTextColor', proxyTextColor);
        provide('proxySize', proxySize);
        provide('proxyMax', proxyMax);
        provide('proxyMin', proxyMin);
        provide('update', update);
        provide('border', true);
    

</script>

Checkbox-group.vue Style

<style lang='less' scoped>
.v-radio-group 
    display: flex;

</style>

Checkbox-button.vue Template

<template>
    <div 
    :class='["v-radio-button", 
     disabled: proxyDisabled || disabled || computedDisabled , 
     medium: proxySize === "medium" ,
     small: proxySize === "small" ,
     mini: proxySize === "mini" ,
     disabledChecked: computedChecked && (proxyDisabled || disabled || computedDisabled) , 
     "v-radio-button-checked": computedChecked && !computedDisabled,  border ]' 
    :style=' 
        backgroundColor: (computedChecked && !proxyDisabled && !disabled && !computedDisabled)? proxyFill : "", 
        color: (computedChecked && !proxyDisabled && !disabled && !computedDisabled)? proxyTextColor : ""
    '
    @click.stop='handleChecked'>
        <input type="checkbox" :checked='computedChecked' :disabled='disabled' :name='name || modelValue || proxyValue' :value='label'>
        <span
        :style=' color: (computedChecked && !proxyDisabled && !disabled && !computedDisabled)? proxyTextColor : "" '
        ><slot></slot></span>
    </div>
</template>

Checkbox-button.vue Script

<script>
import  computed, inject  from 'vue';
export default 
    name: 'checkbox-button',
    props: 
        name: String, // 原生 name 属性
        label: [Number, String, Boolean], // Radio 的 value
        disabled:  // 是否禁用
            type: Boolean,
            default: () => 
                return false
            
        ,
    ,
    setup (props, ctx) 
        const proxyValue = inject('proxyValue');
        const proxyDisabled = inject('proxyDisabled');
        const proxySize = inject('proxySize');
        const proxyFill = inject('proxyFill');
        const proxyTextColor = inject('proxyTextColor');
        const proxyMin = inject('proxyMin');
        const proxyMax = inject('proxyMax');
        const update = inject('update');
        const border = inject('border');

        const handleChecked = () => 
            if (!computedChecked.value && !computedDisabled.value) 
                ctx.emit('change', props.label);
            
            if (!props.disabled && !(proxyDisabled && proxyDisabled.value) && !computedDisabled.value) 
                update(props.label);
            
        ;

        const computedDisabled = computed(() => 
            var bool = false;
            if (proxyMax || proxyMin) 
                if (proxyMax && proxyValue.value.length >= proxyMax.value) 
                    if (!computedChecked.value) 
                        bool = true;
                    
                 else if (proxyMin && proxyValue.value.length <= proxyMin.value) 
                    if (computedChecked.value) 
                        bool = true;
                    
                
            
            return bool;
        );

        const computedChecked = computed(() => 
            return proxyValue.value.find(item => item === props.label);
        );

        return 
            handleChecked,
            proxyValue,
            computedChecked,
            proxyDisabled,
            proxySize,
            border,
            proxyFill,
            proxyTextColor,
            computedDisabled
        
    

</script>

Checkbox-button.vue Style

<style lang='less' scoped>
.v-radio-button 
    display: inline-block;
    padding: 12px 18px;
    border-radius: 4px;
    border: 1px solid #dcdfe6;
    cursor: pointer;
    transition: .3s;
    input 
        display: none;
    
    span 
        color: #606266;
        font-weight: 500;
        font-size: 14px;
        white-space: nowrap;
        transition: .3s;
        user-select: none;
    
    &:hover 
        span 
            color: #409eff;
        
    

.v-radio-button-checked 
    background-color: #409eff;
    span 
        color: #fff;
    
    &:hover 
        span 
            color: #fff;
        
    

.medium 
    padding: 10px 16px;

.small 
    padding: 8px 14px;

.mini 
    padding: 6px 12px;

.disabled 
    border-color: #dcdfe6;
    background-color: #fff;
    cursor: not-allowed;
    span 
        color: #c0c4cc;
    
    &:hover 
        span 
            color: #c0c4cc;
        
    

.disabledChecked 
    background-color: #f2f6fc;
    span 
        color: #c0c4cc;
    
    &:hover 
        span 
            color: #c0c4cc;
        
    

.border 
    border-radius: 0;
    border-right: none;
    &:first-child 
        border-radius: 4px 0 0 4px;
    
    &:last-child 
        border-right: 1px solid #dcdfe6;
        border-radius: 0 4px 4px 0;
    

</style>

index.js 出口文件中引入组件

// Checkbox 单选框
import Checkbox from './components/Checkbox/Checkbox.vue';
import CheckboxGroup from './components/Checkbox/components/Checkbox-group.vue';
import CheckboxButton from './components/Checkbox/components/Checkbox-button.vue';

const Vair = function(Vue) 
    // Checkbox 单选框
    Vue.component(`v-$Checkbox.name`, Checkbox);
    Vue.component(`v-$CheckboxGroup.name`, CheckboxGroup);
    Vue.component(`v-$CheckboxButton.name`, CheckboxButton);


export default Vair;
复制代码

使用组件

  • 在main.js中引入
import  createApp  from 'vue'; 
import App from './App.vue'; 
import Vair from './libs/vair/index.js'; 
const app = createApp(App); 
app.use(Vair).mount('#app');

App.vue中调用

<template>
    <div class='checkbox'>
        <div class='box'>
            <p>基础用法</p>
            <div class='son'>
                <v-checkbox v-model="checked" @change='change'>上海</v-checkbox>
            </div>
        </div>

        <div class='box'>
            <p>禁用状态</p>
            <div class='son'>
                <v-checkbox v-model="checked1" @change='change' disabled>上海</v-checkbox>
                <v-checkbox v-model="checked2" @change='change' disabled>北京</v-checkbox>
            </div>
        </div>

        <div class='box'>
            <p>多选框组</p>
            <div class='son radio-group'>
                <v-checkbox-group v-model="checked3" @change='change' class='radio-group'>
                    <v-checkbox @change='change' label='上海'>上海</v-checkbox>
                    <v-checkbox @change='change' label='北京'>北京</v-checkbox>
                    <v-checkbox @change='change' label='广州'>广州</v-checkbox>
                    <v-checkbox @change='change' label='深圳'>深圳</v-checkbox>
                    <v-checkbox @change='change' label='耶路撒冷'>耶路撒冷</v-checkbox>
                </v-checkbox-group>
            </div>
        </div>

        <div class='box'>
            <p>indeterminate 状态</p>
            <div class='son radio-group' style='display: block'>
                <v-checkbox @change='handleCheckAllChange' :indeterminate='indeterminate' v-model="checkAll">全选</v-checkbox>
                <div style="margin: 15px 0;"></div>
                <v-checkbox-group v-model="checked4" @change='handleCheckedCitiesChange' class='radio-group'>
                    <v-checkbox v-for='city in data' :key='city' :label='city' @change='change'> city </v-checkbox>
                </v-checkbox-group>
            </div>
        </div>

        <div class='box'>
            <p>可选项目数量的限制</p>
            <div class='son radio-group' style='display: block'>
                <v-checkbox-group v-model="checked5" @change='change' :min='min' :max='max' class='radio-group'>
                    <v-checkbox v-for='city in data1' :key='city' :label='city' @change='change'> city </v-checkbox>
                </v-checkbox-group>
            </div>
        </div>
        
        <div class='box'>
            <p>按钮样式</p>
            <div class='son radio-group'>
                <v-checkbox-group v-model="checked6" @change='change' class='radio-group'>
                    <v-checkbox-button @change='change' label='上海'>上海</v-checkbox-button>
                    <v-checkbox-button @change='change' label='北京'>北京</v-checkbox-button>
                    <v-checkbox-button @change='change' label='广州'>广州</v-checkbox-button>
                    <v-checkbox-button @change='change' label='深圳'>深圳</v-checkbox-button>
                    <v-checkbox-button @change='change' label='耶路撒冷'>耶路撒冷</v-checkbox-button>
                </v-checkbox-group>
            </div>
            
            <div class='son radio-group'>
                <v-checkbox-group v-model="checked8" @change='change' size='medium' class='radio-group'>
                    <v-checkbox-button @change='change' label='上海'>上海</v-checkbox-button>
                    <v-checkbox-button @change='change' label='北京'>北京</v-checkbox-button>
                    <v-checkbox-button @change='change' label='广州'>广州</v-checkbox-button>
                    <v-checkbox-button @change='change' label='深圳'>深圳</v-checkbox-button>
                    <v-checkbox-button @change='change' label='耶路撒冷'>耶路撒冷</v-checkbox-button>
                </v-checkbox-group>
            </div>

            <div class='son radio-group'>
                <v-checkbox-group v-model="checked9" @change='change' size='small' class='radio-group'>
                    <v-checkbox-button @change='change' label='上海'>上海</v-checkbox-button>
                    <v-checkbox-button @change='change' label='北京'>北京</v-checkbox-button>
                    <v-checkbox-button @change='change' label='广州'>广州</v-checkbox-button>
                    <v-checkbox-button @change='change' label='深圳'>深圳</v-checkbox-button>
                    <v-checkbox-button @change='change' label='耶路撒冷'>耶路撒冷</v-checkbox-button>
                </v-checkbox-group>
            </div>

            <div class='son radio-group'>
                <v-checkbox-group v-model="checked10" disabled @change='change' size='mini' class='radio-group'>
                    <v-checkbox-button @change='change' label='上海'>上海</v-checkbox-button>
                    <v-checkbox-button @change='change' label='北京'>北京</v-checkbox-button>
                    <v-checkbox-button @change='change' label='广州'>广州</v-checkbox-button>
                    <v-checkbox-button @change='change' label='深圳'>深圳</v-checkbox-button>
                    <v-checkbox-button @change='change' label='耶路撒冷'>耶路撒冷</v-checkbox-button>
                </v-checkbox-group>
            </div>
        </div>

        <div class='box'>
            <p>带边框</p>
            <div class='son'>
                <v-checkbox v-model="checked7" @change='change' border>选项一</v-checkbox>
                <v-checkbox v-model="checked7" @change='change' border>选项二</v-checkbox>
            </div>

            <div class='son'>
                <v-checkbox v-model="checked7" @change='change' size='medium' border>选项一</v-checkbox>
                <v-checkbox v-model="checked7" @change='change' size='medium' border>选项二</v-checkbox>
            </div>

            <div class='son'>
                <v-checkbox v-model="checked7" @change='change' size='small' border>选项一</v-checkbox>
                <v-checkbox v-model="checked7" @change='change' size='small' border>选项二</v-checkbox>
            </div>

            <div class='son'>
                <v-checkbox v-model="checked7" @change='change' size='mini' border>选项一</v-checkbox>
                <v-checkbox v-model="checked7" @change='change' size='mini' border>选项二</v-checkbox>
            </div>
        </div>
    </div>
</template>

<script>
import  ref  from 'vue';
export default 
    setup () 
        const min = ref(1);
        const max = ref(3);
        const checked = ref(true);
        const checked1 = ref(false);
        const checked2 = ref(true);
        const checked3 = ref(['上海', '北京']);
        const data = ref(['上海', '北京', '广州', '深圳']);
        const checked4 = ref(['上海', '北京']);
        const checkAll = ref(false);
        const indeterminate = ref(true);
        const data1 = ref(['上海', '北京', '广州', '深圳']);
        const checked5 = ref(['上海', '北京']);
        const checked6 = ref(['上海']);
        const checked8 = ref(['上海']);
        const checked9 = ref(['上海']);
        const checked10 = ref(['上海']);
        const checked7 = ref(true);
        const change = (label) => 
            console.log(label)
        ;

        const handleCheckAllChange = (val) => 
            checked4.value = val? data.value : [];
            indeterminate.value = false;
        ;
        
        const handleCheckedCitiesChange = (value) => 
            let checkedCount = value.length;
            checkAll.value = checkedCount === data.value.length;
            indeterminate.value = checkedCount > 0 && checkedCount < data.value.length;
        ;

        return 
            checked,
            checked1,
            checked2,
            checked3,
            checked4,
            checkAll,
            data,
            data1,
            checked5,
            checked6,
            checked7,
            checked8,
            checked9,
            checked10,
            indeterminate,
            handleCheckAllChange,
            handleCheckedCitiesChange,
            change,
            min,
            max
        
    

</script>

<style lang='less' scoped>
.checkbox 
    .box 
        margin-bottom: 50px;
        p 
            margin-bottom: 20px;
            font-size: 14px;
        
        .son 
            width: 200px;
            display: flex;
            margin-bottom: 10px;
            justify-content: space-between;           
        
        .radio-group 
            margin-bottom: 10px;
            width: 300px;
        
    

</style>

以上是关于:Checkbox组件的主要内容,如果未能解决你的问题,请参考以下文章

《uni-app》表单组件-Checkbox组件

qt4.8.3中checkbox的大小如何改变?不是整个checkbox的尺寸,是中间那个打钩的小方块的尺寸。

微信小程序checkbox样式修改

Flutter学习日记之表单组件Radio单选框&Checkbox复选框的使用

原子设计:如何设计组件体系

鸿蒙开发(12)---Checkbox组件