: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组件