大家好今天的内容是基于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