From fe68ffa050f8ff2f4b4137ff5bb15e6b395d1592 Mon Sep 17 00:00:00 2001 From: Kagol Date: Wed, 6 Apr 2022 20:20:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(tree):=20=E5=B0=86=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=94=B9=E9=80=A0=E6=88=90=E5=B8=A6=E5=8F=82=E7=9A=84=E5=BD=A2?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui-vue/devui/tree/src/core/README.md | 2 +- .../devui/tree/src/core/use-check.ts | 47 ++++---- .../devui-vue/devui/tree/src/core/use-core.ts | 112 +++++++++--------- .../devui/tree/src/core/use-disable.ts | 64 +++++----- .../devui/tree/src/core/use-operate.ts | 104 ++++++++-------- .../devui/tree/src/core/use-select.ts | 36 +++--- .../devui/tree/src/core/use-toggle.ts | 50 ++++---- .../devui/tree/src/core/use-tree-types.ts | 2 + .../devui-vue/devui/tree/src/core/use-tree.ts | 4 +- .../devui-vue/devui/tree/src/new-tree.tsx | 17 ++- 10 files changed, 232 insertions(+), 206 deletions(-) diff --git a/packages/devui-vue/devui/tree/src/core/README.md b/packages/devui-vue/devui/tree/src/core/README.md index a90993dba3..edae3d6da1 100644 --- a/packages/devui-vue/devui/tree/src/core/README.md +++ b/packages/devui-vue/devui/tree/src/core/README.md @@ -22,7 +22,7 @@ const data = [ { label: 'Leaf node 2' } ]; -const { getExpendedTree } = useTree(data, [useSelect, useCheck]); +const { getExpendedTree } = useTree(data, [useSelect(), useCheck()]); ``` ## API diff --git a/packages/devui-vue/devui/tree/src/core/use-check.ts b/packages/devui-vue/devui/tree/src/core/use-check.ts index 30f986595a..69bfec4a4e 100644 --- a/packages/devui-vue/devui/tree/src/core/use-check.ts +++ b/packages/devui-vue/devui/tree/src/core/use-check.ts @@ -1,28 +1,33 @@ import { Ref } from 'vue'; -import { IInnerTreeNode, IUseCore } from './use-tree-types'; +import { CheckStrategy, IInnerTreeNode, IUseCore } from './use-tree-types'; -export default function useCheck(data: Ref, core: IUseCore) { - const { setNodeValue, getNode } = core; +export default function(options?: { + checkStrategy: CheckStrategy +}) { + return function useCheck(data: Ref, core: IUseCore) { + console.log('useCheck options:', options); + const { setNodeValue, getNode } = core; - const checkNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'checked', true); - } - - const uncheckNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'checked', false); - } + const checkNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'checked', true); + } - const toggleCheckNode = (node: IInnerTreeNode): void => { - if (getNode(node).checked) { + const uncheckNode = (node: IInnerTreeNode): void => { setNodeValue(node, 'checked', false); - } else { - setNodeValue(node, 'checked', true); } - } - return { - checkNode, - uncheckNode, - toggleCheckNode, - } -} \ No newline at end of file + const toggleCheckNode = (node: IInnerTreeNode): void => { + if (getNode(node).checked) { + setNodeValue(node, 'checked', false); + } else { + setNodeValue(node, 'checked', true); + } + } + + return { + checkNode, + uncheckNode, + toggleCheckNode, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-core.ts b/packages/devui-vue/devui/tree/src/core/use-core.ts index 3ab73b8f66..63585a18b0 100644 --- a/packages/devui-vue/devui/tree/src/core/use-core.ts +++ b/packages/devui-vue/devui/tree/src/core/use-core.ts @@ -2,71 +2,73 @@ import { computed, ComputedRef, Ref } from 'vue'; import { IInnerTreeNode, ITreeNode, IUseCore, valueof } from './use-tree-types'; import { generateInnerTree } from './utils'; -export default function useCore(data: Ref): IUseCore { - console.log('useCore:', data, data.value); +export default function(options?){ + return function useCore(data: Ref): IUseCore { + console.log('useCore:', data, data.value); - const getLevel = (node: ITreeNode): number => { - return data.value.find((item) => item.id === node.id).level; - } - - const getChildren = (node: ITreeNode, expanded = false): IInnerTreeNode[] => { - let result = []; - const treeData = expanded ? getExpendedTree() : data; - const startIndex = treeData.value.findIndex((item) => item.id === node.id); - - for (let i = startIndex + 1; i < treeData.value.length && getLevel(node) < treeData.value[i].level; i++) { - result.push(treeData.value[i]); + const getLevel = (node: ITreeNode): number => { + return data.value.find((item) => item.id === node.id).level; } - return result; - } - - const getExpendedTree = (): ComputedRef => { - return computed(() => { - let excludeNodes: IInnerTreeNode[] = []; + const getChildren = (node: ITreeNode, expanded = false): IInnerTreeNode[] => { let result = []; + const treeData = expanded ? getExpendedTree() : data; + const startIndex = treeData.value.findIndex((item) => item.id === node.id); - for (let i = 0, len = data?.value.length; i < len; i++) { - const item = data?.value[i]; + for (let i = startIndex + 1; i < treeData.value.length && getLevel(node) < treeData.value[i].level; i++) { + result.push(treeData.value[i]); + } + + return result; + } - if (excludeNodes.map(node => node.id).includes(item.id)) { - continue; - } - - if (item.expanded !== true) { - excludeNodes = getChildren(item); - } + const getExpendedTree = (): ComputedRef => { + return computed(() => { + let excludeNodes: IInnerTreeNode[] = []; + let result = []; - result.push(item); - } + for (let i = 0, len = data?.value.length; i < len; i++) { + const item = data?.value[i]; - return result; - }); - } + if (excludeNodes.map(node => node.id).includes(item.id)) { + continue; + } + + if (item.expanded !== true) { + excludeNodes = getChildren(item); + } - const getIndex = (node: ITreeNode): number => { - return data.value.findIndex((item) => item.id === node.id); - } + result.push(item); + } - const getNode = (node: ITreeNode): IInnerTreeNode => { - return data.value.find((item) => item.id === node.id); - } + return result; + }); + } - const setNodeValue = (node: IInnerTreeNode, key: keyof IInnerTreeNode, value: valueof): void => { - data.value[getIndex(node)][key] = value; - } + const getIndex = (node: ITreeNode): number => { + return data.value.findIndex((item) => item.id === node.id); + } - const setTree = (newTree: ITreeNode[]): void => { - data.value = generateInnerTree(newTree); - } + const getNode = (node: ITreeNode): IInnerTreeNode => { + return data.value.find((item) => item.id === node.id); + } - return { - getLevel, - getChildren, - getExpendedTree, - getIndex, - getNode, - setNodeValue, - setTree, - } -} \ No newline at end of file + const setNodeValue = (node: IInnerTreeNode, key: keyof IInnerTreeNode, value: valueof): void => { + data.value[getIndex(node)][key] = value; + } + + const setTree = (newTree: ITreeNode[]): void => { + data.value = generateInnerTree(newTree); + } + + return { + getLevel, + getChildren, + getExpendedTree, + getIndex, + getNode, + setNodeValue, + setTree, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-disable.ts b/packages/devui-vue/devui/tree/src/core/use-disable.ts index 259b4a218c..be0c940161 100644 --- a/packages/devui-vue/devui/tree/src/core/use-disable.ts +++ b/packages/devui-vue/devui/tree/src/core/use-disable.ts @@ -1,39 +1,41 @@ import { Ref } from 'vue'; import { IInnerTreeNode, IUseCore } from './use-tree-types'; -export default function useDisable(data: Ref, core: IUseCore) { - const { setNodeValue } = core; - - const disableSelectNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableSelect', true); - } +export default function(options?) { + return function useDisable(data: Ref, core: IUseCore) { + const { setNodeValue } = core; + + const disableSelectNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableSelect', true); + } - const disableCheckNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableCheck', true); - } + const disableCheckNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableCheck', true); + } - const disableToggleNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableToggle', true); - } - - const enableSelectNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableSelect', false); - } + const disableToggleNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableToggle', true); + } + + const enableSelectNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableSelect', false); + } - const enableCheckNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableCheck', false); - } + const enableCheckNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableCheck', false); + } - const enableToggleNode = (node: IInnerTreeNode): void => { - setNodeValue(node, 'disableToggle', false); - } + const enableToggleNode = (node: IInnerTreeNode): void => { + setNodeValue(node, 'disableToggle', false); + } - return { - disableSelectNode, - disableCheckNode, - disableToggleNode, - enableSelectNode, - enableCheckNode, - enableToggleNode, - } -} \ No newline at end of file + return { + disableSelectNode, + disableCheckNode, + disableToggleNode, + enableSelectNode, + enableCheckNode, + enableToggleNode, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-operate.ts b/packages/devui-vue/devui/tree/src/core/use-operate.ts index 077d5b4d06..94d9d06c37 100644 --- a/packages/devui-vue/devui/tree/src/core/use-operate.ts +++ b/packages/devui-vue/devui/tree/src/core/use-operate.ts @@ -1,56 +1,58 @@ import { Ref } from 'vue'; import { IInnerTreeNode, ITreeNode, IUseCore } from './use-tree-types'; -export default function useOperate(data: Ref, core: IUseCore) { - console.log('useOperate:', data, data.value); - - const { setNodeValue, getChildren, getIndex, getLevel } = core; - - const insertBefore = ( - parentNode: ITreeNode, - node: ITreeNode, - referenceNode: ITreeNode, - ): void => { - const children = getChildren(parentNode); - const lastChild = children[children.length - 1]; - let insertedIndex = getIndex(parentNode) + 1; - - if (referenceNode) { - insertedIndex = getIndex(referenceNode); - } else if (lastChild) { - insertedIndex = getIndex(lastChild) + 1; +export default function(options?) { + return function useOperate(data: Ref, core: IUseCore) { + console.log('useOperate:', data, data.value, options); + + const { setNodeValue, getChildren, getIndex, getLevel } = core; + + const insertBefore = ( + parentNode: ITreeNode, + node: ITreeNode, + referenceNode: ITreeNode, + ): void => { + const children = getChildren(parentNode); + const lastChild = children[children.length - 1]; + let insertedIndex = getIndex(parentNode) + 1; + + if (referenceNode) { + insertedIndex = getIndex(referenceNode); + } else if (lastChild) { + insertedIndex = getIndex(lastChild) + 1; + } + + setNodeValue(parentNode, 'expanded', true); + setNodeValue(parentNode, 'isLeaf', false); + + const currentNode = { + ...node, + level: getLevel(parentNode) + 1, + parentId: parentNode.id, + isLeaf: true, + }; + + data.value = data.value.slice(0, insertedIndex) + .concat( + currentNode, + data.value.slice(insertedIndex, data.value.length) + ); } - setNodeValue(parentNode, 'expanded', true); - setNodeValue(parentNode, 'isLeaf', false); - - const currentNode = { - ...node, - level: getLevel(parentNode) + 1, - parentId: parentNode.id, - isLeaf: true, - }; - - data.value = data.value.slice(0, insertedIndex) - .concat( - currentNode, - data.value.slice(insertedIndex, data.value.length) - ); - } - - const removeNode = (node: ITreeNode): void => { - data.value = data.value.filter(item => { - return item.id !== node.id && !getChildren(node).map(nodeItem => nodeItem.id).includes(item.id); - }); - } - - const editNode = (node: IInnerTreeNode, label: string): void => { - setNodeValue(node, 'label', label); - } - - return { - insertBefore, - removeNode, - editNode, - } -} \ No newline at end of file + const removeNode = (node: ITreeNode): void => { + data.value = data.value.filter(item => { + return item.id !== node.id && !getChildren(node).map(nodeItem => nodeItem.id).includes(item.id); + }); + } + + const editNode = (node: IInnerTreeNode, label: string): void => { + setNodeValue(node, 'label', label); + } + + return { + insertBefore, + removeNode, + editNode, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-select.ts b/packages/devui-vue/devui/tree/src/core/use-select.ts index 14378f0008..fbb02b9b4e 100644 --- a/packages/devui-vue/devui/tree/src/core/use-select.ts +++ b/packages/devui-vue/devui/tree/src/core/use-select.ts @@ -1,26 +1,28 @@ import { ref, Ref } from 'vue'; import { IInnerTreeNode, IUseCore } from './use-tree-types'; -export default function useSelect(data: Ref, core: IUseCore) { - const { setNodeValue } = core; +export default function(options?) { + return function useSelect(data: Ref, core: IUseCore) { + const { setNodeValue } = core; - let prevActiveNode: IInnerTreeNode; + let prevActiveNode: IInnerTreeNode; - const selectNode = (node: IInnerTreeNode): void => { - if (node.disableSelect) { return; } + const selectNode = (node: IInnerTreeNode): void => { + if (node.disableSelect) { return; } - if (node.id === prevActiveNode?.id) { return; } + if (node.id === prevActiveNode?.id) { return; } - if (prevActiveNode) { - const prevActiveNodeIndex = data.value.findIndex(item => item.id === prevActiveNode.id) - setNodeValue(data.value[prevActiveNodeIndex], 'selected', false); + if (prevActiveNode) { + const prevActiveNodeIndex = data.value.findIndex(item => item.id === prevActiveNode.id) + setNodeValue(data.value[prevActiveNodeIndex], 'selected', false); + } + + setNodeValue(node, 'selected', true); + prevActiveNode = node; } - - setNodeValue(node, 'selected', true); - prevActiveNode = node; - } - return { - selectNode, - } -} \ No newline at end of file + return { + selectNode, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-toggle.ts b/packages/devui-vue/devui/tree/src/core/use-toggle.ts index cbdfdad712..46e1b69ced 100644 --- a/packages/devui-vue/devui/tree/src/core/use-toggle.ts +++ b/packages/devui-vue/devui/tree/src/core/use-toggle.ts @@ -1,34 +1,36 @@ import { Ref } from 'vue'; import { IInnerTreeNode, IUseCore } from './use-tree-types'; -export default function useToggle(data: Ref, core: IUseCore) { - const { getNode, setNodeValue } = core; +export default function(options?){ + return function useToggle(data: Ref, core: IUseCore) { + const { getNode, setNodeValue } = core; - const expandNode = (node: IInnerTreeNode): void => { - if (node.disableToggle) { return; } + const expandNode = (node: IInnerTreeNode): void => { + if (node.disableToggle) { return; } - setNodeValue(node, 'expanded', true); - } + setNodeValue(node, 'expanded', true); + } - const collapseNode = (node: IInnerTreeNode): void => { - if (node.disableToggle) { return; } - - setNodeValue(node, 'expanded', false); - } + const collapseNode = (node: IInnerTreeNode): void => { + if (node.disableToggle) { return; } + + setNodeValue(node, 'expanded', false); + } - const toggleNode = (node: IInnerTreeNode): void => { - if (node.disableToggle) { return; } + const toggleNode = (node: IInnerTreeNode): void => { + if (node.disableToggle) { return; } - if (getNode(node).expanded) { - setNodeValue(node, 'expanded', false); - } else { - setNodeValue(node, 'expanded', true); + if (getNode(node).expanded) { + setNodeValue(node, 'expanded', false); + } else { + setNodeValue(node, 'expanded', true); + } } - } - return { - expandNode, - collapseNode, - toggleNode, - } -} \ No newline at end of file + return { + expandNode, + collapseNode, + toggleNode, + } + }; +} diff --git a/packages/devui-vue/devui/tree/src/core/use-tree-types.ts b/packages/devui-vue/devui/tree/src/core/use-tree-types.ts index 27785d5f59..8bfc318aba 100644 --- a/packages/devui-vue/devui/tree/src/core/use-tree-types.ts +++ b/packages/devui-vue/devui/tree/src/core/use-tree-types.ts @@ -69,3 +69,5 @@ export interface IUseToggle { export type IUseTree = { treeData: Ref } & IUseCore & IUseToggle & IUseSelect & IUseCheck & IUseDisable & IUseOperate; + +export type CheckStrategy = 'upward' | 'downward' | 'both' | 'none'; diff --git a/packages/devui-vue/devui/tree/src/core/use-tree.ts b/packages/devui-vue/devui/tree/src/core/use-tree.ts index 393c97b951..83e0f617a9 100644 --- a/packages/devui-vue/devui/tree/src/core/use-tree.ts +++ b/packages/devui-vue/devui/tree/src/core/use-tree.ts @@ -4,13 +4,13 @@ import useToggle from './use-toggle'; import useCore from './use-core'; import { generateInnerTree } from './utils'; -export const DEFAULT_TREE_PLUGINS = [useCore, useToggle]; +export const DEFAULT_TREE_PLUGINS = [useCore(), useToggle()]; export default function useTree(tree: ITreeNode[], plugins = []): Partial { const treeData = ref(generateInnerTree(tree)); // TODO: useCore会在useTree是执行两次的问题待解决 - const core: IUseCore = useCore(treeData); + const core: IUseCore = useCore()(treeData); const pluginMethods = DEFAULT_TREE_PLUGINS.concat(plugins).reduce((acc, plugin) => { return { ...acc, ...plugin(treeData, core) }; diff --git a/packages/devui-vue/devui/tree/src/new-tree.tsx b/packages/devui-vue/devui/tree/src/new-tree.tsx index c1e3db7bc7..f1681d085f 100644 --- a/packages/devui-vue/devui/tree/src/new-tree.tsx +++ b/packages/devui-vue/devui/tree/src/new-tree.tsx @@ -1,5 +1,5 @@ import { defineComponent, PropType, provide, renderSlot, toRefs, useSlots, watch } from 'vue'; -import type { ITreeNode } from './core/use-tree-types'; +import type { ITreeNode, IUseTree } from './core/use-tree-types'; import DTreeNode from './components/tree-node'; import DTreeNodeContent from './components/tree-node-content'; import DTreeNodeToggle from './components/tree-node-toggle'; @@ -16,21 +16,30 @@ export default defineComponent({ data: { type: Object as PropType, default: [] - } + }, + plugins: { + type: Object as PropType, + default: [] + }, }, setup(props, { slots }) { const { data } = toRefs(props); const treeFactory = useTree( data.value, - [useSelect, useCheck, useOperate] + [ + useSelect(), + useCheck({ + checkStrategy: 'none', + }), + useOperate(), + ] ); const { setTree, getExpendedTree, toggleNode, - insertBefore, } = treeFactory; // 外部同步内部