From 371d0ea267b8e52c57990757854db5b2d1d6e561 Mon Sep 17 00:00:00 2001 From: unfound <448217185@qq.com> Date: Thu, 12 Aug 2021 21:21:49 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20=E6=9B=B4=E6=94=B9input=E5=80=BC?= =?UTF-8?q?=E7=9A=84=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91=EF=BC=9B=E6=9B=B4?= =?UTF-8?q?=E6=94=B9options=E7=9A=84=E6=98=BE=E7=A4=BA=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=9B=E5=A2=9E=E5=8A=A0=E7=BC=93=E5=AD=98options=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9B=E5=A2=9E=E5=8A=A0=E5=A4=9A=E9=80=89?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E4=BD=86=E5=8A=9F=E8=83=BD=E6=9C=AA=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/checkbox/src/checkbox.tsx | 10 +-- devui/checkbox/src/use-checkbox.ts | 6 +- devui/select/hooks/use-cache-options.ts | 18 +++++ devui/select/src/select.scss | 9 +++ devui/select/src/select.tsx | 88 ++++++++++++++++--------- devui/select/src/use-select.ts | 15 ++++- devui/select/src/utils.ts | 2 + 7 files changed, 108 insertions(+), 40 deletions(-) create mode 100644 devui/select/hooks/use-cache-options.ts diff --git a/devui/checkbox/src/checkbox.tsx b/devui/checkbox/src/checkbox.tsx index 6aaab369..a4f59dae 100644 --- a/devui/checkbox/src/checkbox.tsx +++ b/devui/checkbox/src/checkbox.tsx @@ -5,14 +5,14 @@ import { checkboxGroupInjectionKey, checkboxProps, CheckboxProps } from './use-c export default defineComponent({ name: 'DCheckbox', props: checkboxProps, - emits: ['change', 'update:checked'], + emits: ['change', 'update:modelValue'], setup (props: CheckboxProps, ctx) { const checkboxGroupConf = inject(checkboxGroupInjectionKey, null); const mergedDisabled = computed(() => { return checkboxGroupConf?.disabled.value || props.disabled; }); const mergedChecked = computed(() => { - return checkboxGroupConf ? checkboxGroupConf.isItemChecked(props.value) : props.checked; + return checkboxGroupConf ? checkboxGroupConf.isItemChecked(props.value) : props.modelValue; }); const mergedIsShowTitle = computed(() => { return checkboxGroupConf ? checkboxGroupConf.isShowTitle : props.isShowTitle; @@ -42,13 +42,13 @@ export default defineComponent({ return Promise.resolve(true); }; const toggle = () => { - const isChecked = !props.checked; + const isChecked = !props.modelValue; checkboxGroupConf?.toggleGroupVal(props.value); - ctx.emit('update:checked', isChecked); + ctx.emit('update:modelValue', isChecked); ctx.emit('change', isChecked); }; const handleClick = () => { - canChange(!props.checked, props.value).then(res => res && toggle()); + canChange(!props.modelValue, props.value).then(res => res && toggle()); }; return { diff --git a/devui/checkbox/src/use-checkbox.ts b/devui/checkbox/src/use-checkbox.ts index 86f34bcd..2f903f3a 100644 --- a/devui/checkbox/src/use-checkbox.ts +++ b/devui/checkbox/src/use-checkbox.ts @@ -35,13 +35,13 @@ export const checkboxProps = { type: Boolean, default: false }, - checked: { + modelValue: { type: Boolean, default: false }, value: { type: String, - required: true + default: '' }, label: { type: String, @@ -51,7 +51,7 @@ export const checkboxProps = { type: String, default: undefined }, - 'onUpdate:checked' : { + 'onUpdate:modelValue' : { type: Function as PropType<(v: boolean) => void>, default: undefined }, diff --git a/devui/select/hooks/use-cache-options.ts b/devui/select/hooks/use-cache-options.ts new file mode 100644 index 00000000..0f27abd3 --- /dev/null +++ b/devui/select/hooks/use-cache-options.ts @@ -0,0 +1,18 @@ +import { ComputedRef, computed } from 'vue'; +import { OptionObjectItem } from '../src/use-select'; +import { KeyType } from '../src/utils'; + +export default function (mergeOptions: ComputedRef): any { + const cacheOptions = computed(() => { + const map = new Map, OptionObjectItem>(); + mergeOptions.value.forEach((item) => { + map.set(item.value, item); + }); + return map; + }); + + const getValuesOption = (values: KeyType[]) => + values.map((value) => cacheOptions.value.get(value)); + + return getValuesOption; +} diff --git a/devui/select/src/select.scss b/devui/select/src/select.scss index f520b07d..b8b89f97 100644 --- a/devui/select/src/select.scss +++ b/devui/select/src/select.scss @@ -47,6 +47,15 @@ $select-item-min-height: 36px; } } +.devui-dropdown-menu-multiple { + .devui-select-item { + &.active { + color: $devui-list-item-active-text; + background-color: transparent; + } + } +} + .devui-select-selection { position: relative; } diff --git a/devui/select/src/select.tsx b/devui/select/src/select.tsx index b164187c..4f96cb1d 100644 --- a/devui/select/src/select.tsx +++ b/devui/select/src/select.tsx @@ -1,7 +1,13 @@ -import { defineComponent, ref, Transition, toRefs } from 'vue'; -import { selectProps, SelectProps, OptionItem } from './use-select'; -import DIcon from '../../icon/src/icon'; +import { defineComponent, ref, Transition, toRefs, computed } from 'vue'; +import { + selectProps, + SelectProps, + OptionObjectItem, +} from './use-select'; +import { Icon } from '../../icon'; +import { Checkbox } from '../../checkbox'; import { className } from './utils'; +import useCacheOptions from '../hooks/use-cache-options'; import './select.scss'; export default defineComponent({ @@ -15,52 +21,69 @@ export default defineComponent({ ctx.emit('toggleChange', bool); } - const inputValue = ref(props.modelValue + ''); - initInputValue(); - - function initInputValue() { - props.options.forEach((item) => { - if (typeof item === 'object' && item.value === props.modelValue) { - inputValue.value = item.name; + const mergeOptions = computed(() => { + return props.options.map((item) => { + let option: OptionObjectItem; + if (typeof item === 'object') { + option = { + name: item.name ? item.name : item.value + '', + value: item.value, + checked: false, + ...item, + }; + } else { + option = { + name: item + '', + value: item, + checked: false, + }; } + + return option; }); - } + }); + + const getValuesOption = useCacheOptions(mergeOptions); - function valueChange(item: OptionItem, index: number) { - const value = typeof item === 'object' ? item.value : item; - inputValue.value = getInputValue(item); - ctx.emit('update:modelValue', value); - ctx.emit('valueChange', item, index); + const inputValue = computed(() => { + if (props.multiple && Array.isArray(props.modelValue)) { + const selectedOptions = getValuesOption(props.modelValue); + return selectedOptions.map((item) => item.name).join(','); + } else if (!Array.isArray(props.modelValue)) { + return getValuesOption([props.modelValue])[0]?.name || ''; + } + return '' + }); + + function valueChange(item: OptionObjectItem, index: number) { + ctx.emit('update:modelValue', item.value); + ctx.emit('valueChange', props.options[index], index); toggleChange(false); } - function getItemClassName(item: OptionItem) { - const value = typeof item === 'object' ? item.value : item; + function getItemClassName(item: OptionObjectItem) { return className('devui-select-item', { - active: value === props.modelValue, + active: item.value === props.modelValue, }); } - function getInputValue(item: OptionItem) { - const value = typeof item === 'object' ? item.name : item; - return value + ''; - } - return { + ...toRefs(props), isOpen, inputValue, + mergeOptions, valueChange, toggleChange, getItemClassName, - ...toRefs(props), }; }, render() { const { - options, + mergeOptions, isOpen, inputValue, size, + multiple, placeholder, overview, valueChange, @@ -70,6 +93,7 @@ export default defineComponent({ const selectClassName = className('devui-select', { 'devui-select-open': isOpen, + 'devui-dropdown-menu-multiple': multiple, 'devui-select-lg': size === 'lg', 'devui-select-sm': size === 'sm', 'devui-select-underlined': overview === 'underlined', @@ -90,16 +114,16 @@ export default defineComponent({ placeholder={placeholder} readonly onClick={() => toggleChange(!isOpen)} - onBlur={() => toggleChange(false)} + // onBlur={() => toggleChange(false)} /> - +
    - {options.map((item, i) => ( + {mergeOptions.map((item, i) => (
  • { valueChange(item, i); @@ -107,7 +131,11 @@ export default defineComponent({ class={getItemClassName(item)} key={i} > - {typeof item === 'object' ? item.name : item} + {multiple ? ( + + ) : ( + item.name + )}
  • ))}
diff --git a/devui/select/src/use-select.ts b/devui/select/src/use-select.ts index 60b40ee1..9f2b80d5 100644 --- a/devui/select/src/use-select.ts +++ b/devui/select/src/use-select.ts @@ -3,14 +3,21 @@ import { PropType, ExtractPropTypes } from 'vue'; export interface OptionObjectItem { name: string value: string | number + checked: boolean [key: string]: any } -export type OptionItem = number | string | OptionObjectItem; + +export type OptionItem = + | number + | string + | ({ value: string | number; } & Partial); export type Options = Array; +export type ModelValue = number | string | Array; + export const selectProps = { modelValue: { - type: [String, Number] as PropType, + type: [String, Number, Array] as PropType, default: '', }, 'onUpdate:modelValue': { @@ -33,6 +40,10 @@ export const selectProps = { type: String, default: '请选择', }, + multiple: { + type: Boolean, + default: false, + }, onToggleChange: { type: Function as PropType<(bool: boolean) => void>, default: undefined, diff --git a/devui/select/src/utils.ts b/devui/select/src/utils.ts index 3092da77..1bab1268 100644 --- a/devui/select/src/utils.ts +++ b/devui/select/src/utils.ts @@ -17,3 +17,5 @@ export function className( return classname; } + +export type KeyType = T[K] -- Gitee From 66c19c0b7ae7911661cf2bd7ff96b4e23b53e709 Mon Sep 17 00:00:00 2001 From: unfound <448217185@qq.com> Date: Fri, 13 Aug 2021 18:51:17 +0800 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=E5=A4=9A=E9=80=89=E5=88=9D?= =?UTF-8?q?=E6=AD=A5=E5=AE=8C=E6=88=90=EF=BC=9B=E5=A4=9A=E9=80=89demo?= =?UTF-8?q?=EF=BC=9B=E7=82=B9=E5=87=BBselect=E5=A4=96=E8=BE=B9=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E4=B8=8B=E6=8B=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../select/hooks/use-select-outside-click.ts | 34 +++++++++++++++++++ devui/select/src/select.tsx | 30 +++++++++++----- devui/select/src/use-select.ts | 2 +- sites/components/select/index.md | 10 ++++++ .../components/select/mutiple-select-demo.vue | 19 +++++++++++ 5 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 devui/select/hooks/use-select-outside-click.ts create mode 100644 sites/components/select/mutiple-select-demo.vue diff --git a/devui/select/hooks/use-select-outside-click.ts b/devui/select/hooks/use-select-outside-click.ts new file mode 100644 index 00000000..958ea2bb --- /dev/null +++ b/devui/select/hooks/use-select-outside-click.ts @@ -0,0 +1,34 @@ +import { Ref, onMounted, onBeforeUnmount } from 'vue'; + +export default function ( + refs: Ref[], + isOpen: Ref, + toggleChange: (isOpen: boolean) => void +): void { + function onGlobalMouseDown(e: MouseEvent) { + let target = e.target as HTMLElement; + + /** + * TODO: 需要去了解下shadow DOM + */ + if (target.shadowRoot && e.composed) { + target = (e.composedPath()[0] || target) as HTMLElement; + } + + const element = [refs[0]?.value, refs[1]?.value]; + if ( + isOpen.value && + element.every((el) => el && !el.contains(target) && el !== target) + ) { + toggleChange(false); + } + } + + onMounted(() => { + document.body.addEventListener('mousedown', onGlobalMouseDown, false); + }); + + onBeforeUnmount(() => { + document.body.addEventListener('mousedown', onGlobalMouseDown, false); + }); +} diff --git a/devui/select/src/select.tsx b/devui/select/src/select.tsx index 4f96cb1d..f805f712 100644 --- a/devui/select/src/select.tsx +++ b/devui/select/src/select.tsx @@ -8,6 +8,7 @@ import { Icon } from '../../icon'; import { Checkbox } from '../../checkbox'; import { className } from './utils'; import useCacheOptions from '../hooks/use-cache-options'; +import useSelectOutsideClick from '../hooks/use-select-outside-click'; import './select.scss'; export default defineComponent({ @@ -15,11 +16,14 @@ export default defineComponent({ props: selectProps, emits: ['toggleChange', 'valueChange', 'update:modelValue'], setup(props: SelectProps, ctx) { + const containerRef = ref(null) + const dropdownRef = ref(null) const isOpen = ref(false); function toggleChange(bool: boolean) { isOpen.value = bool; ctx.emit('toggleChange', bool); } + useSelectOutsideClick([containerRef, dropdownRef], isOpen, toggleChange) const mergeOptions = computed(() => { return props.options.map((item) => { @@ -56,9 +60,16 @@ export default defineComponent({ }); function valueChange(item: OptionObjectItem, index: number) { - ctx.emit('update:modelValue', item.value); - ctx.emit('valueChange', props.options[index], index); - toggleChange(false); + let { modelValue } = props + if (props.multiple) { + item.checked = !item.checked + modelValue = mergeOptions.value.filter(item => item.checked).map(item => item.value) + ctx.emit('update:modelValue', modelValue); + } else { + ctx.emit('update:modelValue', item.value); + toggleChange(false); + } + ctx.emit('valueChange', item, index); } function getItemClassName(item: OptionObjectItem) { @@ -70,6 +81,8 @@ export default defineComponent({ return { ...toRefs(props), isOpen, + containerRef, + dropdownRef, inputValue, mergeOptions, valueChange, @@ -105,7 +118,7 @@ export default defineComponent({ }); return ( -
+
toggleChange(!isOpen)} - // onBlur={() => toggleChange(false)} />
- +
    {mergeOptions.map((item, i) => (
  • { + onClick={(e: MouseEvent) => { + e.preventDefault() + e.stopPropagation() valueChange(item, i); }} class={getItemClassName(item)} key={i} > {multiple ? ( - + ) : ( item.name )} diff --git a/devui/select/src/use-select.ts b/devui/select/src/use-select.ts index 9f2b80d5..04678f73 100644 --- a/devui/select/src/use-select.ts +++ b/devui/select/src/use-select.ts @@ -21,7 +21,7 @@ export const selectProps = { default: '', }, 'onUpdate:modelValue': { - type: Function as PropType<(val: string | number) => void>, + type: Function as PropType<(val: ModelValue) => void>, default: undefined, }, options: { diff --git a/sites/components/select/index.md b/sites/components/select/index.md index 4af9aadc..c4d3703b 100644 --- a/sites/components/select/index.md +++ b/sites/components/select/index.md @@ -32,6 +32,12 @@
    +#### Mutiple + +
    + +
    + ```html @@ -44,8 +50,12 @@ -- Gitee From dcffb07506d14540c9ddd10fd8819dc78e5b03b6 Mon Sep 17 00:00:00 2001 From: unfound <448217185@qq.com> Date: Tue, 17 Aug 2021 15:06:37 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20disabled=E5=8A=9F=E8=83=BD=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/select/src/select.scss | 28 +++++++++- devui/select/src/select.tsx | 56 +++++++++++-------- devui/select/src/use-select.ts | 10 +++- .../select/disabled-select-demo.vue | 53 ++++++++++++++++++ sites/components/select/index.md | 10 +++- 5 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 sites/components/select/disabled-select-demo.vue diff --git a/devui/select/src/select.scss b/devui/select/src/select.scss index b8b89f97..54f2150f 100644 --- a/devui/select/src/select.scss +++ b/devui/select/src/select.scss @@ -41,6 +41,25 @@ $select-item-min-height: 36px; } } +.devui-select-disabled { + cursor: not-allowed; + background-color: $devui-disabled-bg; + border-color: $devui-disabled-line; + color: $devui-disabled-text; + + .devui-select-input { + cursor: not-allowed; + background-color: $devui-disabled-bg; + border-color: $devui-disabled-line; + color: $devui-disabled-text; + } + + .devui-select-arrow { + cursor: not-allowed; + color: $devui-disabled-text; + } +} + .devui-select-open { .devui-select-arrow { transform: rotate3d(0, 0, 1, 180deg); @@ -58,6 +77,7 @@ $select-item-min-height: 36px; .devui-select-selection { position: relative; + cursor: pointer; } .devui-select-input { @@ -150,7 +170,7 @@ $select-item-min-height: 36px; color: $devui-text; cursor: pointer; - &:hover:not(.active) { + &:hover:not(.active):not(.disabled) { color: $devui-list-item-hover-text; background-color: $devui-list-item-hover-bg; } @@ -159,6 +179,12 @@ $select-item-min-height: 36px; color: $devui-list-item-active-text; background-color: $devui-list-item-active-bg; } + + &.disabled { + cursor: not-allowed; + background-color: $devui-disabled-bg; + color: $devui-disabled-text; + } } .devui-scrollbar { diff --git a/devui/select/src/select.tsx b/devui/select/src/select.tsx index f805f712..745bda0a 100644 --- a/devui/select/src/select.tsx +++ b/devui/select/src/select.tsx @@ -1,9 +1,5 @@ -import { defineComponent, ref, Transition, toRefs, computed } from 'vue'; -import { - selectProps, - SelectProps, - OptionObjectItem, -} from './use-select'; +import { defineComponent, ref, Transition, computed } from 'vue'; +import { selectProps, SelectProps, OptionObjectItem } from './use-select'; import { Icon } from '../../icon'; import { Checkbox } from '../../checkbox'; import { className } from './utils'; @@ -16,14 +12,15 @@ export default defineComponent({ props: selectProps, emits: ['toggleChange', 'valueChange', 'update:modelValue'], setup(props: SelectProps, ctx) { - const containerRef = ref(null) - const dropdownRef = ref(null) + const containerRef = ref(null); + const dropdownRef = ref(null); const isOpen = ref(false); function toggleChange(bool: boolean) { + if (props.disabled) return; isOpen.value = bool; ctx.emit('toggleChange', bool); } - useSelectOutsideClick([containerRef, dropdownRef], isOpen, toggleChange) + useSelectOutsideClick([containerRef, dropdownRef], isOpen, toggleChange); const mergeOptions = computed(() => { return props.options.map((item) => { @@ -32,14 +29,14 @@ export default defineComponent({ option = { name: item.name ? item.name : item.value + '', value: item.value, - checked: false, + _checked: false, ...item, }; } else { option = { name: item + '', value: item, - checked: false, + _checked: false, }; } @@ -56,14 +53,18 @@ export default defineComponent({ } else if (!Array.isArray(props.modelValue)) { return getValuesOption([props.modelValue])[0]?.name || ''; } - return '' + return ''; }); function valueChange(item: OptionObjectItem, index: number) { - let { modelValue } = props - if (props.multiple) { - item.checked = !item.checked - modelValue = mergeOptions.value.filter(item => item.checked).map(item => item.value) + const { multiple, optionDisabledKey: disabledKey } = props; + let { modelValue } = props; + if (disabledKey && !!item[disabledKey]) return; + if (multiple) { + item._checked = !item._checked; + modelValue = mergeOptions.value + .filter((item) => item._checked) + .map((item) => item.value); ctx.emit('update:modelValue', modelValue); } else { ctx.emit('update:modelValue', item.value); @@ -73,13 +74,14 @@ export default defineComponent({ } function getItemClassName(item: OptionObjectItem) { + const { optionDisabledKey: disabledKey } = props; return className('devui-select-item', { active: item.value === props.modelValue, + disabled: disabledKey ? !!item[disabledKey] : false, }); } return { - ...toRefs(props), isOpen, containerRef, dropdownRef, @@ -97,6 +99,8 @@ export default defineComponent({ inputValue, size, multiple, + disabled, + optionDisabledKey: disabledKey, placeholder, overview, valueChange, @@ -110,6 +114,7 @@ export default defineComponent({ 'devui-select-lg': size === 'lg', 'devui-select-sm': size === 'sm', 'devui-select-underlined': overview === 'underlined', + 'devui-select-disabled': disabled, }); const inputClassName = className('devui-select-input', { @@ -119,14 +124,17 @@ export default defineComponent({ return (
    -
    +
    toggleChange(!isOpen)} + > toggleChange(!isOpen)} + disabled={disabled} /> @@ -138,15 +146,19 @@ export default defineComponent({ {mergeOptions.map((item, i) => (
  • { - e.preventDefault() - e.stopPropagation() + e.preventDefault(); + e.stopPropagation(); valueChange(item, i); }} class={getItemClassName(item)} key={i} > {multiple ? ( - + ) : ( item.name )} diff --git a/devui/select/src/use-select.ts b/devui/select/src/use-select.ts index 04678f73..d9f25a5f 100644 --- a/devui/select/src/use-select.ts +++ b/devui/select/src/use-select.ts @@ -3,7 +3,7 @@ import { PropType, ExtractPropTypes } from 'vue'; export interface OptionObjectItem { name: string value: string | number - checked: boolean + _checked: boolean [key: string]: any } @@ -44,6 +44,14 @@ export const selectProps = { type: Boolean, default: false, }, + disabled: { + type: Boolean, + default: false + }, + optionDisabledKey: { + type: String, + default: '' + }, onToggleChange: { type: Function as PropType<(bool: boolean) => void>, default: undefined, diff --git a/sites/components/select/disabled-select-demo.vue b/sites/components/select/disabled-select-demo.vue new file mode 100644 index 00000000..0b267d3b --- /dev/null +++ b/sites/components/select/disabled-select-demo.vue @@ -0,0 +1,53 @@ + + + diff --git a/sites/components/select/index.md b/sites/components/select/index.md index c4d3703b..27aca3eb 100644 --- a/sites/components/select/index.md +++ b/sites/components/select/index.md @@ -38,6 +38,12 @@
    +#### Disabled + +
    + +
    + ```html @@ -51,10 +57,12 @@ diff --git a/sites/components/select/index.md b/sites/components/select/index.md index 27aca3eb..4611fd62 100644 --- a/sites/components/select/index.md +++ b/sites/components/select/index.md @@ -44,6 +44,12 @@
    +#### AllowClear + +
    + +
    + ```html @@ -58,11 +64,13 @@ import { defineComponent, ref, reactive } from 'vue' import MutipleSelectDemo from './mutiple-select-demo.vue' import DisabledSelectDemo from './disabled-select-demo.vue' +import AllowClearSelectDemo from './allow-clear-select-demo.vue' export default defineComponent({ components: { MutipleSelectDemo, - DisabledSelectDemo + DisabledSelectDemo, + AllowClearSelectDemo }, setup() { const selectValue1 = ref('') -- Gitee From a714d8db827b29868a960765811fb615f12465ad Mon Sep 17 00:00:00 2001 From: "448217185@qq.com" Date: Wed, 1 Sep 2021 00:25:39 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B=EF=BC=9B=E4=BF=AE=E5=A4=8D=E6=95=B0?= =?UTF-8?q?=E5=AD=97=E5=A4=9A=E9=80=89bug=EF=BC=9B=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/select/__tests__/select.spec.ts | 103 ++++++++++++++++++ devui/select/src/select.tsx | 5 +- .../select/allow-clear-select-demo.vue | 3 +- sites/components/select/index.md | 18 ++- .../components/select/mutiple-select-demo.vue | 2 +- 5 files changed, 123 insertions(+), 8 deletions(-) diff --git a/devui/select/__tests__/select.spec.ts b/devui/select/__tests__/select.spec.ts index d7fcaa9b..d724b6fa 100644 --- a/devui/select/__tests__/select.spec.ts +++ b/devui/select/__tests__/select.spec.ts @@ -111,4 +111,107 @@ describe('select', () => { expect(valueChange).toBeCalledTimes(1); expect(value.value).toBe('test'); }); + + it('select v-model work', async () => { + const value = ref() + const options = reactive([1,2,3]) + const wrapper = mount({ + components: { DSelect }, + template: ``, + setup() { + return { + value, + options, + }; + }, + }); + + const container = wrapper.find('.devui-select'); + const item = container.findAll('.devui-select-item'); + + await container.trigger('click') + await item[1].trigger('click') + expect(value.value).toBe(2) + value.value = 1 + await nextTick() + const input = container.find('.devui-select-input') + expect(input.element.value).toBe('1') + + }); + + it('select disabled work', async () => { + const wrapper = mount(DSelect, { + props: { + disabled: true, + }, + }); + + const container = wrapper.find('.devui-select'); + expect(container.classes()).toContain('devui-select-disabled'); + + const input = wrapper.find('.devui-select-input'); + expect(input.attributes()).toHaveProperty('disabled') + }); + + it('select item disabled work', async () => { + const value = ref([]) + const options = reactive([ + { + name: '多选', + value: 0 + }, { + name: '多选很重要呢', + value: 1, + disabled: true + }, { + name: '多选真的很重要呢', + value: 2, + disabled: false + } + ]) + const wrapper = mount({ + components: { DSelect }, + template: ``, + setup() { + return { + value, + options, + }; + }, + }); + + const container = wrapper.find('.devui-select'); + const item = container.findAll('.devui-select-item'); + + await container.trigger('click') + await nextTick() + expect(item[1].classes()).toContain('disabled') + await item[1].trigger('click') + expect(value.value).toEqual([]) + await item[0].trigger('click') + expect(value.value).toEqual([0]) + + }); + + it('select clear work', async () => { + const value = ref(1) + const options = reactive([1,2,3]) + const wrapper = mount({ + components: { DSelect }, + template: ``, + setup() { + return { + value, + options, + }; + }, + }); + + const container = wrapper.find('.devui-select'); + const clearIcon = container.find('.devui-select-clear'); + + expect(clearIcon.exists()).toBeTruthy() + await clearIcon.trigger('click') + expect(value.value).toBe('') + }); }); diff --git a/devui/select/src/select.tsx b/devui/select/src/select.tsx index 81735f1e..45c359dc 100644 --- a/devui/select/src/select.tsx +++ b/devui/select/src/select.tsx @@ -41,8 +41,11 @@ export default defineComponent({ }; } if (multiple) { + // TODO: 这里mergeOptions依赖了modelValue + // 但是下面点击item更新的时候modelValue又是根据mergeOptions来算出来的 + // 因此可能会多更新一次,后续优化 if (Array.isArray(modelValue)) { - option._checked = modelValue.includes(option.name) + option._checked = modelValue.includes(option.value) } else { option._checked = false } diff --git a/sites/components/select/allow-clear-select-demo.vue b/sites/components/select/allow-clear-select-demo.vue index ef52c024..ca21aa71 100644 --- a/sites/components/select/allow-clear-select-demo.vue +++ b/sites/components/select/allow-clear-select-demo.vue @@ -11,9 +11,8 @@ export default defineComponent({ setup () { const value1 = ref('') const options1 = reactive(['可以清除',2,3]) - let value2 = ref(['多选','当然','也可以','清除']) + const value2 = ref(['多选','当然','也可以','清除']) const options2 = reactive(['多选','当然','也可以','清除']) - console.log(value2); return { diff --git a/sites/components/select/index.md b/sites/components/select/index.md index 4611fd62..158592d9 100644 --- a/sites/components/select/index.md +++ b/sites/components/select/index.md @@ -14,7 +14,7 @@
    -#### Middle +#### Middle(default)
    @@ -51,13 +51,23 @@
    ```html + - + - + - + + + + + + + + + + ``` diff --git a/sites/components/select/disabled-select-demo.vue b/sites/components/select/disabled-select-demo.vue deleted file mode 100644 index 0b267d3b..00000000 --- a/sites/components/select/disabled-select-demo.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - diff --git a/sites/components/select/index.md b/sites/components/select/index.md index 158592d9..5440b1c7 100644 --- a/sites/components/select/index.md +++ b/sites/components/select/index.md @@ -2,123 +2,174 @@ 用于从列表中选择单个或者多个数据 -### 何时使用 +### 基本用法 -需要从列表中选择单个或者多个数据 +:::demo 通过`size`:`sm`,`md(默认)`,`lg`来设置`Select`大小,通过`overview`:`underlined`设置只有下边框样式 -### 基本用法 +```vue + -
    - -
    + +``` +::: -#### Underlined +#### 多选 -
    - -
    +:::demo 通过`multiple`:`true`来开启多选 -#### Mutiple +```vue + -
    - -
    + +``` +::: -#### AllowClear +#### 禁用 -
    - -
    +:::demo 通过`disabled`:`true`来禁用`Select`,通过`option-disabled-key`来设置单个选项禁用,比如设置`disabled`字段,则对象上disabled为`true`时不可选择 -```html - - - - - - - - - - - - - - - - - -``` +```vue + - + +``` +::: + +#### 可清空 + +:::demo 通过`allow-clear`:`true`来设置`Select`可清空 + +```vue + + + + +``` +::: diff --git a/sites/components/select/mutiple-select-demo.vue b/sites/components/select/mutiple-select-demo.vue deleted file mode 100644 index 137768c6..00000000 --- a/sites/components/select/mutiple-select-demo.vue +++ /dev/null @@ -1,19 +0,0 @@ - - - -- Gitee