大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说使用vue构建自己的组件库 — checkbox 多选框「建议收藏」,希望您对编程的造诣更进一步.
说在前面,组件库的UI是参照vant,毕竟自己不会设计,配色和样式用他们的也比较合适,功能上也参照了element-ui,也仅仅只是一个学习项目 组件设计时的一些觉得有点意思的地方,可以跟各位分享一下
Github地址
多选框
可能会用到的场景
- 状态切换
- 表单多选
对组件的设计可以分为样式部分和功能部分考虑
样式上可能需要定制化的部分
定制需要区分全局(多选框组)和局部(单个多选框)
- 禁用状态 | 多选框禁止点击
- 文本禁止点击 | 点击label无法触发
- 选中颜色 | 可以传入css颜色值
- 图标大小 | 可以传入css长度值
- 图标形状 | 默认圆形,可以使用方形图标
- 图标自定义 | 包括使用内置图标 和 使用第三方图片
- 多选框组内联
功能上需要区别应用场景
多选框的组件的设计需要考虑到 两种使用场景的区别, 切换状态 和 表单多选
如果是状态切换时
组件只有一个,需要绑定Boolean类型的v-model值
如果是表单多选
基础多选框组件需要外层被group组件包裹,group绑定一个Array数组类型的v-model值
组件设计初期需要判断在哪种场景使用组件,组件中需要定义计算属性,通过组件是否被group组件包裹,从而判断组件而定应用场景.
parentGroup() {
let parent = this.$parent;
// 这里使用循环的原因是 多选框可能不会直接嵌套在group组中,可能会与cell组件混用,需要向上查找group组件
while (parent) {
if (parent.$options.componentName && parent.$options.componentName === 'JiemiccChockboxGroup') {
break;
}
parent = parent.$parent;
}
return parent;
},
group也会在保存自己的组内多选框,以便实现全选和反选的功能.
多选框组件的许多特性会区别对待两种使用场景:
多选框自身绑定的v-mode值
model: {
get() {
return this.parentGroup
? this.parentGroup.value
: this.value !== undefined
? this.value
: this.selfModel;
},
set(val) {
if (this.parentGroup) {
this.parentGroup.$emit('change', val);
} else if (this.value !== undefined) {
this.$emit('input', val);
} else {
this.selfModel = true;
}
},
model为多选框自身的v-model计算属性
- model的get需要优先获取group的值,其次是组件传入的v-model,selfModel为获取失败时组件自身的缺省值.
- model的set也会分三个部分去区分当前组件的使用场景
自定义样式
checkboxIconSize() {
return this.iconSize || (this.parentGroup && this.parentGroup.iconSize);
},
样式自定义使用计算属性来实现,可全局设置和局部设置,且局部设置优先.
多选框组功能定制
限制选择数
多选时,经常需要限定最大或最小选择数,可以在group组件中传入 min 以及 max 的prop属性,进行控制
isLimitDisbled() {
if (!this.parentGroup) return false;
const { max, min } = this.parentGroup;
return !!(min || max) && (this.model.length <= min && this.checkboxChecked) || (this.model.length >= max && !this.checkboxChecked);
},
计算属性 isLimitDisbled代表着 多选框的限制状态,包括样式和功能上的体现. 我们需要思考在什么情况下限制多选框的选择:
- 当min 和 max 至少有一个限定
- 当前选择组的选定数量小于等于最小数,且选定框当前为选定状态
- 当前选择组的选定数量大于等于最小数,且选定框当前不在选定状态
反选和全选
group组件中定义相关方法,可以在适当的时候触发
chooseToggle(all) {
if (all) {
this.checkboxChild.forEach((child) => {
child.initChecked();
});
} else {
const allValue = this.checkboxChild.map(child => child.label);
const subValue = allValue.filter(val => !this.value.includes(val));
this.$emit('change', subValue);
}
},
- 传入参数all代表全选, 遍历group组件的多选框子组件触发initChecked方法(不是选定更改为选定)
- 不传入参数即为反选, 求得全部可选和已选的差值即可.(之前考虑过模拟触发checkbox的click事件,但是会vue的dom处理时是异步更新的,只会缓存最后一个点击结果的model值)
与cell组件嵌套使用
chooseItem(index) {
this.checkboxChild[index].$el.click();
},
group定义主动点击多选框方法,当cell点击时触发即可. 但是要注意,不能在需要在多选框组件禁止点击冒泡, 不禁止会在点击多选框时同时触发cell点击事件,两这样就两次点击效果相反.
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13889.html