本文已参与「新人创作礼」活动,一起开启掘金创作之路。
涉及技术点
在此模拟element-ui中checkboxGroup、checkbox的封装,并且支持选择对象的形式
使用方式
组件使用1:
label支持传递item对象,但是需要给组件一个唯一标识的键名,这个是必须的 组件使用2、3:element组件的常规使用
<template>
<div>
{{ formData }}
<acc-checkbox-group v-model="formData.groupValObj" label-key="id">
<acc-checkbox v-for="item in checkboxList" :key="item.id" :label="item">
{{ item.name }}
</acc-checkbox>
</acc-checkbox-group>
<acc-checkbox-group v-model="formData.groupValId">
<acc-checkbox
v-for="item in checkboxList"
:key="item.id"
:label="item.id"
>
{{ item.name }}
</acc-checkbox>
</acc-checkbox-group>
<acc-checkbox v-model="formData.checkbox" label="123"></acc-checkbox>
</div>
</template>
<script>
export default {
data () {
return {
formData: {
groupValObj: [
{ "id": 1, "name": "aa" }
]
},
checkboxList: [
{ id: 1, name: 'aa' },
{ id: 2, name: 'bb' },
{ id: 3, name: 'cc' },
]
}
}
}
</script>
<style>
</style>
正题开始
AccCheckboxGroup组件
<template>
<div>
<slot />
</div>
</template>
<script>
export default {
name: 'AccCheckboxGroup',
model: {
prop: 'groupVal',
event: 'changed'
},
provide () {
return {
checkboxGroup: this
}
},
props: {
// checkboxGroup组件 接受到groupVal值
// 之后得触发一下 当前changed事件 动态改变父组件的groupVal值
// checkboxGroup组件 操作 checkbox 组件 -> 使用provide 和 inject
groupVal: {
type: Array,
default () {
return []
}
},
labelKey: {
type: String,
default: ''
}
},
data () {
return {}
},
methods: {}
}
</script>
<style lang="scss" scoped></style>
AccCheckbox组件
inject接收父组件的参数,default可以定义默认值。因为AccCheckbox组件可以单独使用。
<template>
<label :class="['acc_checkbox', { 'is-checked': isChecked }]">
<span class="acc_checkbox_input">
<span class="acc_checkbox_inner"></span>
<input
type="checkbox"
class="acc_checkbox_original"
:name="name"
v-model="model"
:value="label"
/>
</span>
<span class="acc_checkbox_label">
<slot />
<!-- 如果 checkbox 没有传递内容时候 渲染label -->
<template v-if="!$slots.default">{{ label }}</template>
</span>
</label>
</template>
<script>
export default {
name: 'AccCheckbox',
inject: {
checkboxGroup: {
default: ''
}
},
props: {
label: {
type: [String, Number, Boolean, Object],
default: ''
},
value: {
type: Boolean,
default: false
},
name: {
type: String,
default: ''
}
},
data () {
return {}
},
computed: {
model: {
get () {
return this.isCheckGroup ? this.checkboxGroup.groupVal : this.value
},
set (value) {
this.isCheckGroup ? this.checkboxGroup.$emit('changed', value) : this.$emit('input', value)
}
},
isCheckGroup () {
return !!this.checkboxGroup
},
isChecked () {
return this.isCheckGroup
? this.checkboxGroup.labelKey
? this.model.findIndex(i => i[this.checkboxGroup.labelKey] === this.label[this.checkboxGroup.labelKey]) !== -1
: this.model.includes(this.label)
: this.model
}
},
methods: {}
}
</script>
<style lang="scss" scoped>
.acc_checkbox {
color: #606266;
font-weight: 500;
position: relative;
cursor: pointer;
display: inline-block;
white-space: nowrap;
outline: none;
font-size: 14px;
margin-right: 30px;
.acc_checkbox_input {
white-space: nowrap;
cursor: pointer;
outline: none;
display: inline-block;
line-height: 1;
position: relative;
vertical-align: middle;
.acc_checkbox_inner {
border: 1px solid #dcdfe6;
width: 14px;
height: 14px;
background: #fff;
position: relative;
cursor: pointer;
display: inline-block;
box-sizing: border-box;
&:after {
width: 4px;
height: 4px;
border-radius: 100%;
background: #fff;
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) scale(0);
transition: transform 0.15s ease-in;
}
}
.acc_checkbox_original {
opacity: 0;
outline: none;
position: absolute;
z-index: -1;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: 0;
}
}
.acc_checkbox_label {
font-size: 14px;
padding-left: 10px;
}
}
// checkbox 被选中
.acc_checkbox.is-checked {
.acc_checkbox_input {
.acc_checkbox_inner {
border-color: $--color-primary;
background: $--color-primary;
&:after {
transform: translate(-50%, -50%) scale(1);
}
}
}
.acc_checkbox_label {
color: $--color-primary;
}
}
</style>