From d3596a14b9eebf65403d6b39035d0b1f07536cd9 Mon Sep 17 00:00:00 2001 From: lzm <254311563@qq.com> Date: Sun, 14 Nov 2021 13:14:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84tree-select?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=A4=9A=E9=80=89?= =?UTF-8?q?=E5=92=8C=E4=BB=85=E5=8F=B6=E5=AD=90=E8=8A=82=E7=82=B9=E5=8F=AF?= =?UTF-8?q?=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui/tree-select/assets/close.svg | 17 ++ .../devui/tree-select/assets/open.svg | 14 ++ .../devui/tree-select/hooks/use-clear.ts | 26 +++ .../devui/tree-select/hooks/use-select.ts | 72 +++++++ .../devui/tree-select/hooks/use-toggle.ts | 23 +++ packages/devui-vue/devui/tree-select/index.ts | 3 +- .../tree-select/src/tree-select-types.ts | 18 +- .../devui/tree-select/src/tree-select.scss | 40 ++-- .../devui/tree-select/src/tree-select.tsx | 174 +++++++--------- .../devui-vue/devui/tree-select/src/utils.ts | 23 +++ .../docs/components/tree-select/index.md | 185 ++++++++++++------ yarn.lock | 69 +++---- 12 files changed, 416 insertions(+), 248 deletions(-) create mode 100644 packages/devui-vue/devui/tree-select/assets/close.svg create mode 100644 packages/devui-vue/devui/tree-select/assets/open.svg create mode 100644 packages/devui-vue/devui/tree-select/hooks/use-clear.ts create mode 100644 packages/devui-vue/devui/tree-select/hooks/use-select.ts create mode 100644 packages/devui-vue/devui/tree-select/hooks/use-toggle.ts diff --git a/packages/devui-vue/devui/tree-select/assets/close.svg b/packages/devui-vue/devui/tree-select/assets/close.svg new file mode 100644 index 00000000..2bb8e7f8 --- /dev/null +++ b/packages/devui-vue/devui/tree-select/assets/close.svg @@ -0,0 +1,17 @@ + + + + + + diff --git a/packages/devui-vue/devui/tree-select/assets/open.svg b/packages/devui-vue/devui/tree-select/assets/open.svg new file mode 100644 index 00000000..a69af88b --- /dev/null +++ b/packages/devui-vue/devui/tree-select/assets/open.svg @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/packages/devui-vue/devui/tree-select/hooks/use-clear.ts b/packages/devui-vue/devui/tree-select/hooks/use-clear.ts new file mode 100644 index 00000000..ccf1b9fb --- /dev/null +++ b/packages/devui-vue/devui/tree-select/hooks/use-clear.ts @@ -0,0 +1,26 @@ +import { computed } from 'vue' +import type { SetupContext, Ref } from 'vue' +import { TreeSelectProps } from '../src/tree-select-types' + +export default function useToggle(props: TreeSelectProps, ctx: SetupContext, data: Ref): any { + + const isClearable = computed(() => { + return !props.disabled && props.allowClear && data.value.length > 0; + }) + + const handleClear = (e: MouseEvent) => { + e.preventDefault() + e.stopPropagation() + if (props.multiple) { + ctx.emit('update:modelValue', []) + } else { + ctx.emit('update:modelValue', '') + data.value = '' + } + } + + return { + isClearable, + handleClear, + } +} \ No newline at end of file diff --git a/packages/devui-vue/devui/tree-select/hooks/use-select.ts b/packages/devui-vue/devui/tree-select/hooks/use-select.ts new file mode 100644 index 00000000..24d03700 --- /dev/null +++ b/packages/devui-vue/devui/tree-select/hooks/use-select.ts @@ -0,0 +1,72 @@ +import { ref } from 'vue' +import { TreeSelectProps, TreeItem } from '../src/tree-select-types' + +export default function useSelect(props: TreeSelectProps): any { + const inputValue = ref('') + const selectedCache = new Set() + + const selectValue = (item: TreeItem) => { + if(!props.multiple) { + inputValue.value = item.label + } else { + item.checked = !item.checked + if(item.halfchecked) item.halfchecked = false + useCache(item) + searchUp(item) + searchDown(item) + inputValue.value = [...selectedCache].toString() + } + } + + const useCache = (item: TreeItem) => { + item.checked === true + ? selectedCache.add(item.label) + : (selectedCache.has(item.label) && selectedCache.delete(item.label)) + } + + const searchUp = (item: TreeItem) => { + + if(!item.parent) return + let state = '' + const checkedArr = item.parent.children.filter((el) => el.checked === true) + switch(checkedArr.length) { + case 0: + state = 'none' + break; + case item.parent.children.length: + state = 'checked' + break + default: + state = 'halfchecked' + break + } + + if(state === 'checked') { + item.parent.checked = true + item.parent.halfchecked = false + } else if(state === 'halfchecked') { + item.parent.halfchecked = true + item.parent.checked = false + } else { + item.parent.checked = false + item.parent.halfchecked = false + } + + useCache(item.parent) + searchUp(item.parent) + } + + const searchDown = (item: TreeItem) => { + if(!item.children) return + item.children.forEach((el) => { + el.checked = item.checked + useCache(el) + searchDown(el) + }) + } + + return { + inputValue, + selectValue + } +} \ No newline at end of file diff --git a/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts b/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts new file mode 100644 index 00000000..6be5a707 --- /dev/null +++ b/packages/devui-vue/devui/tree-select/hooks/use-toggle.ts @@ -0,0 +1,23 @@ +import { ref } from 'vue' +import { TreeSelectProps, TreeItem } from '../src/tree-select-types' + +export default function useToggle(props: TreeSelectProps): any { + const visible = ref(false) + + const selectToggle = () => { + if(props.disabled) return + visible.value = !visible.value + } + + const treeToggle = (e: MouseEvent, item: TreeItem) => { + e.preventDefault() + e.stopPropagation() + item.opened = ! item.opened + } + + return { + visible, + selectToggle, + treeToggle, + } +} \ No newline at end of file diff --git a/packages/devui-vue/devui/tree-select/index.ts b/packages/devui-vue/devui/tree-select/index.ts index 4a3ed884..1c269221 100644 --- a/packages/devui-vue/devui/tree-select/index.ts +++ b/packages/devui-vue/devui/tree-select/index.ts @@ -10,9 +10,8 @@ export { TreeSelect } export default { title: 'TreeSelect 树形选择框', category: '数据录入', - status: undefined, // TODO: 组件若开发完成则填入"已完成",并删除该注释 + status: '20%', // TODO: 组件若开发完成则填入"已完成",并删除该注释 install(app: App): void { - app.use(TreeSelect as any) } } diff --git a/packages/devui-vue/devui/tree-select/src/tree-select-types.ts b/packages/devui-vue/devui/tree-select/src/tree-select-types.ts index fcb84dcc..0809b4da 100644 --- a/packages/devui-vue/devui/tree-select/src/tree-select-types.ts +++ b/packages/devui-vue/devui/tree-select/src/tree-select-types.ts @@ -1,15 +1,15 @@ import type { PropType, ExtractPropTypes } from 'vue' export interface TreeItem { - id?: number | string - label?: string - data?: any - parent?: TreeItem | null - children?: Array | null + id: number | string + label: string + parent?: TreeItem + children?: Array level?: number loading?: boolean - isOpen?: boolean - isChecked?: boolean + opened?: boolean + checked?: boolean + halfchecked?: boolean disabled?: boolean [prop: string]: any @@ -36,10 +36,6 @@ export const treeSelectProps = { type: Boolean, default: false }, - expandTree: { - type: Boolean, - default: false - }, multiple: { type: Boolean, default: false, diff --git a/packages/devui-vue/devui/tree-select/src/tree-select.scss b/packages/devui-vue/devui/tree-select/src/tree-select.scss index 9cae0512..85b3a783 100644 --- a/packages/devui-vue/devui/tree-select/src/tree-select.scss +++ b/packages/devui-vue/devui/tree-select/src/tree-select.scss @@ -65,7 +65,7 @@ $tree-select-item-font-size: 16px; .devui-tree-select-item { font-size: $tree-select-item-font-size; - display: block; + display: inline-flex; min-height: $tree-select-item-min-height; line-height: 1.5; width: 100%; @@ -77,6 +77,7 @@ $tree-select-item-font-size: 16px; border: 0; color: $devui-text; cursor: pointer; + align-items: center; &:hover:not(.active):not(.disabled) { color: $devui-list-item-hover-text; @@ -84,24 +85,21 @@ $tree-select-item-font-size: 16px; } } -.devui-tree-select-clearable:hover { - .devui-tree-select-clear { - display: inline-flex; - } - - .devui-tree-select-arrow { - display: none; +.devui-tree-select-clearable { + position: relative; + &:hover { + .devui-tree-select-clear { + display: inline-flex; + } + + .devui-tree-select-arrow { + display: none; + } } } -.devui-tree-select-clearable:hover { - .devui-tree-select-clear { - display: inline-flex; - } - - .devui-tree-select-arrow { - display: none; - } +.devui-tree-select-notclearable { + position: relative; } .devui-tree-select-clear, @@ -124,13 +122,3 @@ $tree-select-item-font-size: 16px; } } -.devui-tree-select-arrow-expand { - display: inline-flex; - justify-content: center; - align-items: center; - transform: rotate3d(0, 0, 1, 270deg); -} - -.devui-tree-select-arrow-open { - transform: rotate3d(0, 0, 1, 0deg); -} diff --git a/packages/devui-vue/devui/tree-select/src/tree-select.tsx b/packages/devui-vue/devui/tree-select/src/tree-select.tsx index ed99e34b..dfa35e08 100644 --- a/packages/devui-vue/devui/tree-select/src/tree-select.tsx +++ b/packages/devui-vue/devui/tree-select/src/tree-select.tsx @@ -1,87 +1,40 @@ import './tree-select.scss' -import { defineComponent, ref, reactive, toRefs, computed } from 'vue' -import { treeSelectProps, TreeSelectProps } from './tree-select-types' -import { className } from './utils' +import { defineComponent, ref, Transition } from 'vue' +import type { SetupContext } from 'vue' +import { treeSelectProps, TreeSelectProps, TreeItem } from './tree-select-types' +import { attributeExtension, className } from './utils' +import useToggle from '../hooks/use-toggle' +import useSelect from '../hooks/use-select' +import useClear from '../hooks/use-clear' +import IconOpen from '../assets/open.svg' +import IconClose from '../assets/close.svg' +import Checkbox from '../../checkbox/src/checkbox' export default defineComponent({ name: 'DTreeSelect', props: treeSelectProps, emits: ['toggleChange', 'valueChange', 'update:modelValue'], - setup(props: TreeSelectProps, ctx) { - - const visible = ref(false) - const origin = ref() - const position = reactive({ - originX: 'left', - originY: 'bottom', - overlayX: 'left', - overlayY: 'top' - }) - const inputValue = ref('') - - const { treeData } = toRefs(props) - - const mergeClearable = computed(() => { - return !props.disabled && props.allowClear && inputValue.value.length > 0; - }) - - function toggleChange() { - if (props.disabled) return - visible.value = !visible.value - ctx.emit('toggleChange', visible.value) - } + setup(props: TreeSelectProps, ctx: SetupContext) { + const { treeData, placeholder, disabled, multiple, leafOnly } = props + const { visible, selectToggle, treeToggle} = useToggle(props) + const { inputValue, selectValue } = useSelect(props) + const { isClearable, handleClear} = useClear(props, ctx, inputValue) - function valueChange(data) { - if (data.isOpen !== undefined) { - data.isOpen = !data.isOpen + const clickNode = (item: TreeItem)=> { + if(!leafOnly) { + selectValue(item) + !multiple && selectToggle(item) } else { - inputValue.value = data.label - visible.value = false - ctx.emit('update:modelValue', data.label) - ctx.emit('toggleChange', visible.value) - } - } - - function handleClear(e: MouseEvent) { - e.preventDefault() - e.stopPropagation() - if (props.multiple) { - ctx.emit('update:modelValue', []) - } else { - ctx.emit('update:modelValue', '') - inputValue.value = '' + if(!item.children) { + selectValue(item) + !multiple && selectToggle(item) + } } } - return { - visible, - origin, - position, - inputValue, - mergeClearable, - treeData, - handleClear, - toggleChange, - valueChange, - } - }, - render() { - const { - origin, - position, - inputValue, - mergeClearable, - treeData, - placeholder, - disabled, - handleClear, - toggleChange, - valueChange - } = this - const treeSelectCls = className('devui-tree-select', { - 'devui-tree-select-open': this.visible, + 'devui-tree-select-open': visible.value, 'devui-tree-select-disabled': disabled, }) @@ -89,16 +42,19 @@ export default defineComponent({
{ - e.preventDefault() - e.stopPropagation() - valueChange(item) - }}> - { item.children ? - - - : {'\u00A0\u00A0\u00A0'}} - {item.label} + onClick={() => clickNode(item)} + > + { item.children + ? item.opened + ? treeToggle(e, item)}/> + : treeToggle(e, item)} /> + :{'\u00A0\u00A0\u00A0'} + } + { multiple + ? item.halfchecked + ? + : + : (item.label)}
) @@ -108,7 +64,7 @@ export default defineComponent({ return ( <> { renderNode(item) } - { item.isOpen && renderTree(item.children) } + { item.opened && renderTree(item.children) } ) } @@ -116,30 +72,34 @@ export default defineComponent({ }) } - return ( -
-
- - - - - - - -
- -
-
    {renderTree(treeData)}
+ return () => { + return ( +
+
selectToggle()}> + + handleClear(e)} class="devui-tree-select-clear"> + + + + +
- -
- ) - } + +
+
    {renderTree(attributeExtension(treeData))}
+
+
+
+ ) + } + }, }) diff --git a/packages/devui-vue/devui/tree-select/src/utils.ts b/packages/devui-vue/devui/tree-select/src/utils.ts index 3092da77..30f3136a 100644 --- a/packages/devui-vue/devui/tree-select/src/utils.ts +++ b/packages/devui-vue/devui/tree-select/src/utils.ts @@ -1,3 +1,26 @@ +import { TreeData } from '../src/tree-select-types' + +export function attributeExtension(data: TreeData): any { + data.forEach((el) => { + let level = 1 + el.level = level + const nodeQueue = [] + nodeQueue.push(el) + while(nodeQueue.length !== 0) { + const node = nodeQueue.shift() + if(node.children) { + node.children.forEach((el) => { + el.level = level + 1 + el.parent = node + nodeQueue.push(el) + }) + } + level += 1 + } + }) + return data +} + /** * 动态获取class字符串 * @param classStr 是一个字符串,固定的class名 diff --git a/packages/devui-vue/docs/components/tree-select/index.md b/packages/devui-vue/docs/components/tree-select/index.md index 03a6a904..4e623ddd 100644 --- a/packages/devui-vue/docs/components/tree-select/index.md +++ b/packages/devui-vue/docs/components/tree-select/index.md @@ -18,57 +18,36 @@ export default defineComponent({ const value = ref('') const data = ref([{ label: '一级 1', - level: 1, - isOpen: false, children: [{ label: '二级 1-1', - level: 2, - isOpen: false, children: [{ label: '三级 1-1-1', - level: 3, }] }] }, { label: '一级 2', - level: 1, - isOpen: false, children: [{ label: '二级 2-1', - level: 2, - isOpen: false, children: [{ label: '三级 2-1-1', - level: 3, }] }, { label: '二级 2-2', - level: 2, - isOpen: false, children: [{ label: '三级 2-2-1', - level: 3, }] }] }, { label: '一级 3', - level: 1, - isOpen: false, children: [{ label: '二级 3-1', - level: 2, - isOpen: false, children: [{ label: '三级 3-1-1', - level: 3, }] }, { label: '二级 3-2', - level: 2, - isOpen: false, children: [{ label: '三级 3-2-1', - level: 3, }] }] }]) @@ -100,57 +79,36 @@ export default defineComponent({ const value = ref('') const data = ref([{ label: '一级 1', - level: 1, - isOpen: false, children: [{ label: '二级 1-1', - level: 2, - isOpen: false, children: [{ label: '三级 1-1-1', - level: 3, }] }] }, { label: '一级 2', - level: 1, - isOpen: false, children: [{ label: '二级 2-1', - level: 2, - isOpen: false, children: [{ label: '三级 2-1-1', - level: 3, }] }, { label: '二级 2-2', - level: 2, - isOpen: false, children: [{ label: '三级 2-2-1', - level: 3, }] }] }, { label: '一级 3', - level: 1, - isOpen: false, children: [{ label: '二级 3-1', - level: 2, - isOpen: false, children: [{ label: '三级 3-1-1', - level: 3, }] }, { label: '二级 3-2', - level: 2, - isOpen: false, children: [{ label: '三级 3-2-1', - level: 3, }] }] }]) @@ -182,57 +140,36 @@ export default defineComponent({ const value = ref('') const data = ref([{ label: '一级 1', - level: 1, - isOpen: false, children: [{ label: '二级 1-1', - level: 2, - isOpen: false, children: [{ label: '三级 1-1-1', - level: 3, }] }] }, { label: '一级 2', - level: 1, - isOpen: false, children: [{ label: '二级 2-1', - level: 2, - isOpen: false, children: [{ label: '三级 2-1-1', - level: 3, }] }, { label: '二级 2-2', - level: 2, - isOpen: false, children: [{ label: '三级 2-2-1', - level: 3, }] }] }, { label: '一级 3', - level: 1, - isOpen: false, children: [{ label: '二级 3-1', - level: 2, - isOpen: false, children: [{ label: '三级 3-1-1', - level: 3, }] }, { label: '二级 3-2', - level: 2, - isOpen: false, children: [{ label: '三级 3-2-1', - level: 3, }] }] }]) @@ -246,4 +183,126 @@ export default defineComponent({ ``` +::: + +### 多选 + +:::demo + +```vue + + +``` + +::: + +### 仅叶子节点可选 + +:::demo + +```vue + + +``` + ::: \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 713eb7e3..d36991f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2790,7 +2790,7 @@ "@vue/babel-plugin-jsx" "^1.0.7" hash-sum "^2.0.0" -"@vitejs/plugin-vue@^1.2.3", "@vitejs/plugin-vue@^1.3.0", "@vitejs/plugin-vue@^1.4.0": +"@vitejs/plugin-vue@^1.3.0", "@vitejs/plugin-vue@^1.4.0", "@vitejs/plugin-vue@^1.9.0": version "1.9.4" resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.9.4.tgz#4f48485432cbb986a9fb9d254dc33ce30ddccbfa" integrity sha512-0CZqaCoChriPTTtGkERy1LGPcYjGFpi2uYRhBPIkqJqUGV5JnJFhQAgh6oH9j5XZHfrRaisX8W0xSpO4T7S78A== @@ -2887,7 +2887,7 @@ "@vue/compiler-core" "3.2.21" "@vue/shared" "3.2.21" -"@vue/compiler-sfc@3.2.21", "@vue/compiler-sfc@^3.0.11", "@vue/compiler-sfc@^3.0.5", "@vue/compiler-sfc@^3.1.1", "@vue/compiler-sfc@^3.2.1": +"@vue/compiler-sfc@3.2.21", "@vue/compiler-sfc@^3.0.11", "@vue/compiler-sfc@^3.0.5", "@vue/compiler-sfc@^3.2.1": version "3.2.21" resolved "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.21.tgz#42639ee49e725afb7d8f1d1940e75dc17a56002c" integrity sha512-+yDlUSebKpz/ovxM2vLRRx7w/gVfY767pOfYTgbIhAs+ogvIV2BsIt4fpxlThnlCNChJ+yE0ERUNoROv2kEGEQ== @@ -2951,7 +2951,7 @@ "@vue/shared" "3.2.21" csstype "^2.6.8" -"@vue/server-renderer@3.2.21", "@vue/server-renderer@^3.1.1", "@vue/server-renderer@^3.2.1": +"@vue/server-renderer@3.2.21", "@vue/server-renderer@^3.2.1": version "3.2.21" resolved "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.21.tgz#887d0a44de76f72313cff2686a24c0315231d634" integrity sha512-QBgYqVgI7XCSBCqGa4LduV9vpfQFdZBOodFmq5Txk5W/v1KrJ1LoOh2Q0RHiRgtoK/UR9uyvRVcYqOmwHkZNEg== @@ -5767,7 +5767,7 @@ inquirer@^7.3.3: strip-ansi "^6.0.0" through "^2.3.6" -inquirer@^8.1.2, inquirer@^8.2.0: +inquirer@^8.1.2: version "8.2.0" resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== @@ -7770,7 +7770,7 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -ora@*, ora@^6.0.1: +ora@*: version "6.0.1" resolved "https://registry.npmjs.org/ora/-/ora-6.0.1.tgz#68caa9fd6c485a40d6f46c50a3940fa3df99c7f3" integrity sha512-TDdKkKHdWE6jo/6pIa5U5AWcSVfpNRFJ8sdRJpioGNVPLAzZzHs/N+QhUfF7ZbyoC+rnDuNTKzeDJUbAza9g4g== @@ -8264,7 +8264,7 @@ pretty-format@^27.3.1: ansi-styles "^5.0.0" react-is "^17.0.1" -prismjs@^1.23.0: +prismjs@^1.23.0, prismjs@^1.25.0: version "1.25.0" resolved "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756" integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg== @@ -10007,7 +10007,7 @@ vite-svg-loader@^2.2.0: "@vue/compiler-sfc" "^3.0.11" svgo "^2.3.0" -vite@^2.3.7, vite@^2.4.4: +vite@^2.4.4: version "2.6.13" resolved "https://registry.npmjs.org/vite/-/vite-2.6.13.tgz#16b3ec85a66d5b461ac29a903874d4357f9af432" integrity sha512-+tGZ1OxozRirTudl4M3N3UTNJOlxdVo/qBl2IlDEy/ZpTFcskp+k5ncNjayR3bRYTCbqSOFz2JWGN1UmuDMScA== @@ -10019,9 +10019,21 @@ vite@^2.3.7, vite@^2.4.4: optionalDependencies: fsevents "~2.3.2" -vitepress-theme-demoblock@^1.2.2: +vite@^2.6.5: + version "2.6.14" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.14.tgz#35c09a15e4df823410819a2a239ab11efb186271" + integrity sha512-2HA9xGyi+EhY2MXo0+A2dRsqsAG3eFNEVIo12olkWhOmc8LfiM+eMdrXf+Ruje9gdXgvSqjLI9freec1RUM5EA== + dependencies: + esbuild "^0.13.2" + postcss "^8.3.8" + resolve "^1.20.0" + rollup "^2.57.0" + optionalDependencies: + fsevents "~2.3.2" + +vitepress-theme-demoblock@1.3.2: version "1.3.2" - resolved "https://registry.npmjs.org/vitepress-theme-demoblock/-/vitepress-theme-demoblock-1.3.2.tgz#d423818ee38041b33ecdf9738b3ad3cf4775e40b" + resolved "https://registry.yarnpkg.com/vitepress-theme-demoblock/-/vitepress-theme-demoblock-1.3.2.tgz#d423818ee38041b33ecdf9738b3ad3cf4775e40b" integrity sha512-uyzdb28sq2hSNzU4KeITNayWNPYUqvUWcahcqQZVvAoPlSr1tF9vGraRQWEhAFW//MII3tM/mncYLfICJfmISw== dependencies: camelcase "^6.2.0" @@ -10033,38 +10045,17 @@ vitepress-theme-demoblock@^1.2.2: vitepress "^0.16.1" yaml "^2.0.0-6" -vitepress@^0.15.6: - version "0.15.6" - resolved "https://registry.npmjs.org/vitepress/-/vitepress-0.15.6.tgz#b3d2487384f60deb5e0be7da1f1896c1db75025e" - integrity sha512-+knoqxT6V3DAAP6ojXmwsbplqjPvf256xFJfAJdzu4WArJSXGoserPIhtLK7fOFKPQrcb8S6H9RpIshY31/hLg== +vitepress@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/vitepress/-/vitepress-0.20.1.tgz#34d39950a5062a4efa5621be3a78c005f656faee" + integrity sha512-2SOlvRv0bvPrQ3RPtp7Fh/G1MKidrsgAgYz18OvV+nIJb9iiYo0GUVHKN3OYswMh+vH78NyTeA1Q5v4YJ/H9LQ== dependencies: "@docsearch/css" "^1.0.0-alpha.28" "@docsearch/js" "^1.0.0-alpha.28" - "@types/markdown-it" "^12.0.1" - "@vitejs/plugin-vue" "^1.2.3" - "@vue/compiler-sfc" "^3.1.1" - "@vue/server-renderer" "^3.1.1" - chalk "^4.1.1" - compression "^1.7.4" - debug "^4.3.2" - diacritics "^1.3.0" - escape-html "^1.0.3" - fs-extra "^10.0.0" - globby "^11.0.3" - gray-matter "^4.0.3" - lru-cache "^6.0.0" - markdown-it "^12.0.6" - markdown-it-anchor "^7.1.0" - markdown-it-container "^3.0.0" - markdown-it-emoji "^2.0.0" - markdown-it-table-of-contents "^0.5.2" - minimist "^1.2.5" - ora "^5.4.0" - polka "^0.5.2" - prismjs "^1.23.0" - sirv "^1.0.12" - vite "^2.3.7" - vue "^3.1.1" + "@vitejs/plugin-vue" "^1.9.0" + prismjs "^1.25.0" + vite "^2.6.5" + vue "^3.2.19" vitepress@^0.16.1: version "0.16.1" @@ -10265,7 +10256,7 @@ vue-tsc@^0.2.2: dependencies: vscode-vue-languageservice "^0.27.0" -vue@^3.1.1, vue@^3.2.1: +vue@^3.1.1, vue@^3.2.1, vue@^3.2.19: version "3.2.21" resolved "https://registry.npmjs.org/vue/-/vue-3.2.21.tgz#55f5665172d95cf97e806b9aad0a375180be23a1" integrity sha512-jpy7ckXdyclfRzqLjL4mtq81AkzQleE54KjZsJg/9OorNVurAxdlU5XpD49GpjKdnftuffKUvx2C5jDOrgc/zg== -- Gitee From f83e4d5496c701fc3f5e3159d14d5dd7ccc0c7f3 Mon Sep 17 00:00:00 2001 From: lzm <254311563@qq.com> Date: Sun, 14 Nov 2021 14:25:41 +0800 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9Eapi=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tree-select/__tests__/tree-select.spec.ts | 57 +++++++++++++++++++ .../docs/components/tree-select/index.md | 40 ++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts diff --git a/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts b/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts new file mode 100644 index 00000000..f35fcbe2 --- /dev/null +++ b/packages/devui-vue/devui/tree-select/__tests__/tree-select.spec.ts @@ -0,0 +1,57 @@ +import { mount } from '@vue/test-utils'; +import { ref } from 'vue'; +import DTreeSelect from '../src/tree-select'; + +describe('tree-select', () => { + + it('tree-select should render correctly', async () => { + const value = ref(''); + const data = ref([{ + label: '一级 1', + children: [{ + label: '二级 1-1', + children: [{ + label: '三级 1-1-1', + }] + }] + }, { + label: '一级 2', + children: [{ + label: '二级 2-1', + children: [{ + label: '三级 2-1-1', + }] + }, { + label: '二级 2-2', + children: [{ + label: '三级 2-2-1', + }] + }] + }, { + label: '一级 3', + children: [{ + label: '二级 3-1', + children: [{ + label: '三级 3-1-1', + }] + }, { + label: '二级 3-2', + children: [{ + label: '三级 3-2-1', + }] + }] + }]); + const wrapper = mount({ + components: { DTreeSelect }, + template: ``, + setup() { + return { + value, + data, + }; + }, + }); + + expect(wrapper.classes()).toContain('devui-tree-select'); + }); +}) \ No newline at end of file diff --git a/packages/devui-vue/docs/components/tree-select/index.md b/packages/devui-vue/docs/components/tree-select/index.md index 4e623ddd..97f4017f 100644 --- a/packages/devui-vue/docs/components/tree-select/index.md +++ b/packages/devui-vue/docs/components/tree-select/index.md @@ -8,7 +8,7 @@ ```vue ``` -::: \ No newline at end of file +::: + +### API + +d-select-tree 参数 + +| 参数 | 类型 | 默认 | 说明 | 跳转 | +| ------------ | ------- | ----- | ------------------------------------------------------------------- | ------------------------------------ | +| treeData | TreeData | | 必选,树形选择框的内容 | [基本用法](#基本用法) | +| placeholder | string | '请选择'| 可选,修改输入框的默认显示内容 | [基本用法](#基本用法) | +| disabled | boolean | false | 可选,值为 true 时禁止用户使用 | [禁用](#禁用) | +| allowClear | boolean | false | 可选,值为 true 时可以清空输入框内容 | [可清空](#可清空) | +| multiple | boolean | false | 可选,值为 true 时可选择多个项 | [多选](#多选) | +| leafOnly | boolean | false | 可选,值为 true 时仅可选择叶子节点 | [仅叶子节点可选](#仅叶子节点可选) | + + +### 接口 & 类型定义 + + +```ts +interface TreeItem { + id: number | string + label: string + parent?: TreeItem + children?: Array + level?: number + loading?: boolean + opened?: boolean + checked?: boolean + halfchecked?: boolean + disabled?: boolean + + [prop: string]: any +} + +type TreeData = Array +``` \ No newline at end of file -- Gitee