之前拆解checkbox的v-model的时候,发现其实选择这类的可以统一抽象出来公共逻辑,这样可以脱离选项逻辑,用在任意项目 选择的样式可以灵活多变。
组件的源码
显示
<!-- SelectType.vue -->
<template>
<div>
<div class="option-box" @click="$refs.input.click()">
<slot :isSelected="curChecked"></slot>
</div>
<!-- 原始input隐藏,这里的value看情况使用,可以不传,change是将选择事件抛出去,让父组件知晓 -->
<input
ref="input"
hidden
type="checkbox"
:valueList="curChecked"
:value="value"
@change="changeInput($event)"
/>
</div>
</template>
<script>
export default {
// https://juejin.cn/post/6844904151856447495
name: 'SelectType',
model: {
prop: 'valueList',
event: 'change',
},
props: {
isMultiple: {
default: false,
},
// 整个选中的 值数组
valueList: {
required: true,
default() {
return [];
},
},
// 选项的value值
value: {
required: true,
default() {
return '';
},
},
},
computed: {
selectedList: {
get() {
return [...this.valueList];
},
set() {
console.log();
},
},
curChecked() {
return this.valueList.includes(this.value);
},
},
methods: {
changeInput($event) {
let { valueList } = $event.target;
// 看下选中的值在数组中的索引,这里不用原生的value,因为$event.target.value始终是字符串类型
let index = this.selectedList.indexOf(this.value);
// 选择的时候,selectedList跟着变化
if (this.isMultiple) {
valueList
? this.selectedList.push(this.value)
: index !== -1 && this.selectedList.splice(index, 1);
} else {
this.selectedList.length = 0;
valueList && this.selectedList.push(this.value);
}
this.$emit('change', this.selectedList, $event);
},
},
};
</script>
组件的逻辑
主要用的是原始的checkbox。
- 当父组件传过来的checked是数组类型的时候,当前组件的初始状态curChecked是,看数组里有没有当前value,有就是选中,没有就不选中
- 数组是引用类型,为了不改变父组件的值,这里使用selectedList复制一份checked
- 当checkbox有change事件的时候,
- 多选,选中就将value值push到selectedList,否则删掉,然后将selectedList抛给父组件
- 单选,选中清空selectedList,valueList有的话直接将当前放进去
- !!! 注意这里使用computed,因为别的复选框选择的时候,selectedList也会跟着变化
- slot里面就是具体的dom了,此组件只提供逻辑
组件的使用步骤
使用方法:
<SelectType v-model="valueCur" v-for="(item, index) in options" :key="index" :value="item.value" :isMultiple="isMultiple" >
<div class="option" :class="{selected:isSelected}" :text="item.text" slot-scope="{ isSelected }" :isSelected="isSelected" > {{item.text}} </div>
</SelectType>
.option可以是任意复杂的dom,isSelected是当前项选中与否的值,这样可以灵活增加选中的样式
如果需要动态根据选中得到节点信息,可以加个监听事件 change
SelectType(v-model='selectedCodes' :value='item.code' @change='changeItem')
changeItem(...args){
console.log(...args)
// 两个值,第一个是选中的列表,第二个是原生input的信息
}