From 6af358479bdabedb929280c3a8b034fe90b9a92f Mon Sep 17 00:00:00 2001 From: zcating Date: Mon, 23 Aug 2021 23:39:09 +0800 Subject: [PATCH] =?UTF-8?q?feat(checkbox):=20checkbox=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=20v-model=20=E6=9B=BF=E6=8D=A2=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/checkbox/index.ts | 10 ++- devui/checkbox/src/checkbox-group.tsx | 35 +++++------ devui/checkbox/src/checkbox.tsx | 89 +++++++++++++++------------ devui/checkbox/src/use-checkbox.ts | 17 +++-- sites/components/checkbox/index.md | 18 ++++-- 5 files changed, 98 insertions(+), 71 deletions(-) diff --git a/devui/checkbox/index.ts b/devui/checkbox/index.ts index ef86a03c..8b89c0e7 100644 --- a/devui/checkbox/index.ts +++ b/devui/checkbox/index.ts @@ -1,16 +1,22 @@ import type { App } from 'vue' import Checkbox from './src/checkbox' +import CheckboxGroup from './src/checkbox-group' -Checkbox.install = function(app: App) { +Checkbox.install = function (app: App) { app.component(Checkbox.name, Checkbox) } +CheckboxGroup.install = function (app: App) { + app.component(CheckboxGroup.name, CheckboxGroup) +} + export { Checkbox } export default { title: 'Checkbox 复选框', category: '数据录入', install(app: App): void { - app.use(Checkbox as any) + app.use(Checkbox as any); + app.use(CheckboxGroup as any); } } diff --git a/devui/checkbox/src/checkbox-group.tsx b/devui/checkbox/src/checkbox-group.tsx index ab206d60..677f2ff5 100644 --- a/devui/checkbox/src/checkbox-group.tsx +++ b/devui/checkbox/src/checkbox-group.tsx @@ -6,27 +6,27 @@ import './checkbox-group.scss'; export default defineComponent({ name: 'DCheckboxGroup', props: checkboxGroupProps, - emits: ['change', 'update:value'], - setup (props: ExtractPropTypes, ctx) { - const valList = toRef(props, 'value'); + emits: ['change', 'update:modelValue'], + setup(props: ExtractPropTypes, ctx) { + const valList = toRef(props, 'modelValue'); const defaultOpt = { checked: false, isShowTitle: true, halfchecked: false, showAnimation: true, - disabled: false + disabled: false, }; const toggleGroupVal = (val: string) => { - const index = valList.value.findIndex(item => item === val); + const index = valList.value.findIndex((item) => item === val); if (index === -1) { const res = [...valList.value, val]; - ctx.emit('update:value', res); + ctx.emit('update:modelValue', res); ctx.emit('change', res); return; } valList.value.splice(index, 1); - ctx.emit('update:value', valList.value); + ctx.emit('update:modelValue', valList.value); ctx.emit('change', valList.value); }; const isItemChecked = (itemVal: string) => valList.value.includes(itemVal); @@ -40,35 +40,30 @@ export default defineComponent({ isItemChecked, toggleGroupVal, itemWidth: toRef(props, 'itemWidth'), - direction: toRef(props, 'direction') + direction: toRef(props, 'direction'), }); return { - defaultOpt + defaultOpt, }; }, - render () { - const { - direction, - $slots, - defaultOpt, - options - } = this; + render() { + const { direction, $slots, defaultOpt, options } = this; let children = $slots.default?.(); if (options?.length > 0) { - children = options.map(opt => { + children = options.map((opt) => { const mergedOpt = Object.assign({}, defaultOpt, opt); - return (); + return ; }); } return (
- { children } + {children}
); - } + }, }); diff --git a/devui/checkbox/src/checkbox.tsx b/devui/checkbox/src/checkbox.tsx index 6aaab369..0f9a0ab9 100644 --- a/devui/checkbox/src/checkbox.tsx +++ b/devui/checkbox/src/checkbox.tsx @@ -1,37 +1,43 @@ import { defineComponent, inject, computed } from 'vue'; import './checkbox.scss'; -import { checkboxGroupInjectionKey, checkboxProps, CheckboxProps } from './use-checkbox'; +import { + checkboxGroupInjectionKey, + checkboxProps, + CheckboxProps, +} from './use-checkbox'; export default defineComponent({ name: 'DCheckbox', props: checkboxProps, - emits: ['change', 'update:checked'], - setup (props: CheckboxProps, ctx) { + emits: ['change', 'update:checked', 'update:modelValue'], + setup(props: CheckboxProps, ctx) { const checkboxGroupConf = inject(checkboxGroupInjectionKey, null); + const isChecked = computed(() => props.checked || props.modelValue); const mergedDisabled = computed(() => { return checkboxGroupConf?.disabled.value || props.disabled; }); const mergedChecked = computed(() => { - return checkboxGroupConf ? checkboxGroupConf.isItemChecked(props.value) : props.checked; + return checkboxGroupConf?.isItemChecked?.(props.value) ?? isChecked.value; }); const mergedIsShowTitle = computed(() => { - return checkboxGroupConf ? checkboxGroupConf.isShowTitle : props.isShowTitle; + return checkboxGroupConf?.isShowTitle ?? props.isShowTitle; }); const mergedShowAnimation = computed(() => { - return checkboxGroupConf ? checkboxGroupConf.showAnimation : props.showAnimation; + return checkboxGroupConf?.showAnimation ?? props.showAnimation; }); const mergedColor = computed(() => { - return checkboxGroupConf ? checkboxGroupConf.color : props.color; + return checkboxGroupConf?.color ?? props.color; }); - const itemWidth = checkboxGroupConf ? checkboxGroupConf.itemWidth.value : undefined; - const direction = checkboxGroupConf ? checkboxGroupConf.direction.value : undefined; + const itemWidth = checkboxGroupConf?.itemWidth.value; + const direction = checkboxGroupConf?.direction.value; const canChange = (isChecked: boolean, val: string) => { if (mergedDisabled.value) { return Promise.resolve(false); } - const beforeChange = props.beforeChange || (checkboxGroupConf ? checkboxGroupConf?.beforeChange : undefined); + const beforeChange = + props.beforeChange ?? checkboxGroupConf?.beforeChange; if (beforeChange) { const res = beforeChange(isChecked, val); if (typeof res === 'boolean') { @@ -42,13 +48,14 @@ export default defineComponent({ return Promise.resolve(true); }; const toggle = () => { - const isChecked = !props.checked; + const current = !isChecked.value; checkboxGroupConf?.toggleGroupVal(props.value); - ctx.emit('update:checked', isChecked); - ctx.emit('change', isChecked); + ctx.emit('update:checked', current); + ctx.emit('update:modelValue', current); + ctx.emit('change', current); }; const handleClick = () => { - canChange(!props.checked, props.value).then(res => res && toggle()); + canChange(!isChecked.value, props.value).then((res) => res && toggle()); }; return { @@ -59,10 +66,10 @@ export default defineComponent({ mergedIsShowTitle, mergedChecked, mergedShowAnimation, - handleClick + handleClick, }; }, - render () { + render() { const { itemWidth, direction, @@ -77,45 +84,48 @@ export default defineComponent({ name, value, mergedColor, - $slots + $slots, } = this; const wrapperCls = { 'devui-checkbox-column-margin': direction === 'column', - 'devui-checkbox-wrap': typeof itemWidth !== 'undefined' + 'devui-checkbox-wrap': typeof itemWidth !== 'undefined', }; - const wrapperStyle = itemWidth? [ - `width: ${itemWidth}px` - ] : []; + const wrapperStyle = itemWidth ? [`width: ${itemWidth}px`] : []; const checkboxCls = { 'devui-checkbox': true, active: mergedChecked, halfchecked, disabled: mergedDisabled, - unchecked: !mergedChecked + unchecked: !mergedChecked, }; const labelTitle = mergedIsShowTitle ? title || label : ''; - const bgImgStyle = (mergedColor && halfchecked) || mergedColor ? `linear-gradient(${mergedColor}, ${mergedColor})` : ''; + const bgImgStyle = + (mergedColor && halfchecked) || mergedColor + ? `linear-gradient(${mergedColor}, ${mergedColor})` + : ''; const spanStyle = [ - `border-color:${(mergedChecked || halfchecked) && mergedColor ? mergedColor : ''}`, + `border-color:${ + (mergedChecked || halfchecked) && mergedColor ? mergedColor : '' + }`, `background-image:${bgImgStyle}`, - `background-color:${mergedColor && halfchecked ? mergedColor : ''}` + `background-color:${mergedColor && halfchecked ? mergedColor : ''}`, ]; const spanCls = { 'devui-checkbox-material': true, 'custom-color': mergedColor, 'devui-checkbox-no-label': !label && !$slots.default, 'devui-no-animation': !mergedShowAnimation, - 'devui-checkbox-default-background': !halfchecked + 'devui-checkbox-default-background': !halfchecked, }; const polygonCls = { 'devui-tick': true, - 'devui-no-animation': !mergedShowAnimation + 'devui-no-animation': !mergedShowAnimation, }; const stopPropagation = ($event: Event) => $event.stopPropagation(); const inputProps = { - indeterminate: halfchecked + indeterminate: halfchecked, }; return ( @@ -130,17 +140,22 @@ export default defineComponent({ checked={mergedChecked} disabled={mergedDisabled} onClick={stopPropagation} - onChange={stopPropagation} /> - + onChange={stopPropagation} + /> + - + class="devui-checkbox-tick" + > + - { - label || $slots.default?.() - } + {label || $slots.default?.()} ); - } + }, }); diff --git a/devui/checkbox/src/use-checkbox.ts b/devui/checkbox/src/use-checkbox.ts index 86f34bcd..a3d3f0b3 100644 --- a/devui/checkbox/src/use-checkbox.ts +++ b/devui/checkbox/src/use-checkbox.ts @@ -41,7 +41,6 @@ export const checkboxProps = { }, value: { type: String, - required: true }, label: { type: String, @@ -51,13 +50,19 @@ export const checkboxProps = { type: String, default: undefined }, - 'onUpdate:checked' : { + 'onUpdate:checked': { type: Function as PropType<(v: boolean) => void>, default: undefined }, onChange: { type: Function as PropType<(v: boolean) => void>, default: undefined + }, + modelValue: { + type: String, + }, + 'onUpdate:modelValue': { + type: Function as PropType<(v: boolean) => void> } } as const; @@ -65,9 +70,9 @@ export type CheckboxProps = ExtractPropTypes; export const checkboxGroupProps = { ...commonProps, - value: { + modelValue: { type: Array as PropType, - required: true + required: true, }, direction: { type: String as PropType, @@ -78,14 +83,14 @@ export const checkboxGroupProps = { default: undefined }, options: { - type: Array as PropType<({value: string;} & Partial)[]>, + type: Array as PropType<({ value: string; } & Partial)[]>, default: () => [] }, onChange: { type: Function as PropType<(v: string[]) => void>, default: undefined }, - 'onUpdate:value': { + 'onUpdate:modelValue': { type: Function as PropType<(v: string[]) => void>, default: undefined } diff --git a/sites/components/checkbox/index.md b/sites/components/checkbox/index.md index ee370b2b..a0acd62a 100644 --- a/sites/components/checkbox/index.md +++ b/sites/components/checkbox/index.md @@ -9,14 +9,21 @@ ### 基本用法 - - + + ```html - - + + ``` +#### 使用 CheckboxGroup + + + + +
{{ checkedValues.reduce((prev, current) => `${current} ${prev}`, '') }}
+