源码: 地址
由于自己最近一直在使用 Vue3
,本着学了不用就作废的原则就自己尝试着写了 UI 组件示例。而刚开始选择的就是多选框这个组件。
多选框 Checkbox
组件是平时使用频率蛮高的一个组件,我们现在一步步来完善自己的组件。
开始
先定义组件
选项
创建组件 Checkbox.vue
文件
对 Checkbox
进行美化,主要先隐藏 input[type=checkbox]
再对 input[type=checkbox]:checked
选择器进行处理
逻辑处理
先定义 props
选项
我们知道 Vue3
对于 v-model
的处理和以前稍稍有点不同。
由文档所述,其中的 prop
的 value
变成了 modelValue
,所以我们组件内定义的 props
需要改变
props: {
modelValue: {
type: [Boolean, Number, String],
default: () => undefined
}
}
我们利用 computed
实现双向绑定
setup(props, { emit }) {
const model = computed({
get() {
return props.modelValue;
},
set(val) {
emit("update:modelValue", val);
},
});
return {
model
}
}
再添加事件回调
这里需要注意,emit
事件时需要在 emits
中注册
emits: ['change'],
setup(props, { emit }) {
...
const onChange = () => {
emit('change', model.value);
}
return {
onChange
}
},
由此,一个简单的 checkbox
组件就完成了。不过我们现在使用的 composition-api
形式,我们可以封装一下整个逻辑 useCheckbox
函数
import { getCurrentInstance } from 'vue';
export function useCheckbox(props) {
const { proxy } = getCurrentInstance()
const model = computed({
get() {
return props.modelValue;
},
set(val) {
proxy.emit("update:modelValue", val);
},
});
const onChange = () => {
proxy.emit('change', model.value);
}
return {
model,
onChange
}
}
再在组件中引入
import { useCheckbox } from './useCheckbox';
setup(props) {
return useCheckbox(props);
}
多选框组
我们使用了很多 UI 库组件,checkbox
存在多选,大多数组件库也有这个多选组,我们接下来封装一个多选框组。
新建一个 checkbox-group.vue
文件
而实际使用时,我们利用 checkbox-group
包裹 checkbox
组件
选项一
选项二
选项三
模板文件我们已经写完了,接下来我们来完善逻辑;这里利用 provide/inject
来传递父组件参数
export default {
name: 'AniCheckboxGroup',
props: {
modelValue: {
type: [Array],
default: () => undefined
}
},
emits: ['change'],
setup(props, ctx) {
// 定义事件
const changeEvent = value => {
ctx.emit('update:modelValue', value);
nextTick(() => {
ctx.emit('change, value);
});
};
const modelValue = computed({
get() {
return props.modelValue;
},
set(val) {
changeEvent(val);
}
});
// 向子组件传递
provide('CheckboxGroup', {
name: 'CheckboxGroup',
modelValue,
...toRefs(props),
changeEvent
});
}
}
子组件中 inject
接收
// 接收父组件消息
export const useCheckboxGroup = () => {
// 这里的名称对应 provide 名称
const checkboxGroup = inject('CheckboxGroup', {});
// 判断是否为多选框组
const isGroup = computed(
() => checkboxGroup && checkboxGroup.name === 'CheckboxGroup'
);
return {
isGroup,
checkboxGroup
};
};
useCheckbox
中需要判断是否为多选框组,具体思路看注释吧,其实逻辑也简单~
export const useCheckbox = props => {
const { emit } = getCurrentInstance();
const { isGroup, checkboxGroup } = useCheckboxGroup();
// 存在多选组,则使用多选组 modelValue
const store = computed(() =>
checkboxGroup ? checkboxGroup.modelValue.value : props.modelValue
);
// 还是判断多选组
const model = computed({
get() {
return isGroup.value ? store.value : props.modelValue;
},
set(val) {
if (isGroup.value && Array.isArray(val)) {
checkboxGroup.changeEvent(val);
} else {
emit('update:modelValue', val);
}
}
});
// 判断多选框是否选中
const isChecked = computed(() => {
const value = model.value;
if (isPropType(value, 'boolean')) {
return value;
} else if (isPropType(value, 'array')) {
return value.includes(props.label);
}
return null;
});
const onChange = e => {
const target = e.target;
const value = target.checked ? true : false;
emit('change', value, e);
};
return {
model,
isChecked,
onChange
};
};
这里模板需要修改,我们需要传入选中的选项字段 value
和多选框是否选中 checked
总结
还是要自己动手封装,组件内的一些细节和思路对于业务逻辑还是有一定的启发作用。
欢迎关注【前端学啥】一起交流