: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组件的主要内容,如果未能解决你的问题,请参考以下文章
qt4.8.3中checkbox的大小如何改变?不是整个checkbox的尺寸,是中间那个打钩的小方块的尺寸。