vue封装通用选择组件
之前拆解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的信息 }