From 7e01a7cf94bee4f820cd5725adbb1ab5201b8721 Mon Sep 17 00:00:00 2001 From: Kagol Date: Wed, 6 Apr 2022 11:14:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(tree):=20=E5=A2=9E=E5=8A=A0=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E8=BF=9E=E6=8E=A5=E7=BA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devui/tree/src/components/tree-node.tsx | 39 ++++++++++------ .../tree/src/components/use-tree-node.ts | 45 +++++++++++++++++++ packages/devui-vue/devui/tree/src/const.ts | 2 + .../devui-vue/devui/tree/src/core/use-core.ts | 9 ++-- .../devui/tree/src/core/use-tree-types.ts | 4 +- packages/devui-vue/devui/tree/src/tree.scss | 24 +++++++++- .../devui-vue/docs/components/tree/index.md | 28 +++++++++++- 7 files changed, 128 insertions(+), 23 deletions(-) create mode 100644 packages/devui-vue/devui/tree/src/components/use-tree-node.ts diff --git a/packages/devui-vue/devui/tree/src/components/tree-node.tsx b/packages/devui-vue/devui/tree/src/components/tree-node.tsx index fa1df6dde5..f5e70e5d0f 100644 --- a/packages/devui-vue/devui/tree/src/components/tree-node.tsx +++ b/packages/devui-vue/devui/tree/src/components/tree-node.tsx @@ -1,8 +1,9 @@ import { defineComponent, inject, PropType, toRefs } from 'vue'; -import { USE_TREE_TOKEN } from '../const'; +import { NODE_HEIGHT, USE_TREE_TOKEN } from '../const'; import { IInnerTreeNode } from '../core/use-tree-types'; import DTreeNodeToggle from './tree-node-toggle'; import { Checkbox } from '../../../checkbox'; +import useTreeNode from './use-tree-node'; export default defineComponent({ name: 'DTreeNode', @@ -15,22 +16,32 @@ export default defineComponent({ const { data } = toRefs(props); const { selectNode, toggleCheckNode } = inject(USE_TREE_TOKEN); + const { + nodeClass, + nodeStyle, + nodeContentClass, + nodeTitleClass, + nodeVLineClass, + nodeVLineStyle, + nodeHLineClass, + } = useTreeNode(data); + return () => { return ( -
-
{ - selectNode(data.value); - }}> +
+ +
{ selectNode(data.value); }}> + -
- { { - toggleCheckNode(data.value); - }} onClick={(event: MouseEvent) => { - event.stopPropagation(); - }} /> } - {data.value?.label} +
+ { toggleCheckNode(data.value); }} + onClick={(event: MouseEvent) => { event.stopPropagation(); }} + /> + {data.value?.label}
diff --git a/packages/devui-vue/devui/tree/src/components/use-tree-node.ts b/packages/devui-vue/devui/tree/src/components/use-tree-node.ts new file mode 100644 index 0000000000..3acdebc2f8 --- /dev/null +++ b/packages/devui-vue/devui/tree/src/components/use-tree-node.ts @@ -0,0 +1,45 @@ +import { computed, ComputedRef, inject } from 'vue'; +import { NODE_HEIGHT, NODE_INDENT, USE_TREE_TOKEN } from '../const'; +import { IInnerTreeNode, IUseTree } from '../core/use-tree-types'; + +export default function useTreeNode(data: ComputedRef) { + const { getChildren } = inject(USE_TREE_TOKEN); + + const nodeClass = computed(() => [ + 'devui-tree-node', + data.value?.expanded && 'devui-tree-node__open', + ]); + const nodeStyle = computed(() => {return { paddingLeft: `${NODE_INDENT * (data.value?.level - 1)}px` }}); + + const nodeVLineClass = computed(() => [ + !data.value?.isLeaf && data.value?.expanded && 'devui-tree-node__vline', + ]); + const nodeVLineStyle = computed(() => {return { + height: `${NODE_HEIGHT * (getChildren(data.value, true).length - 1) + NODE_HEIGHT / 2 + 1}px`, + left: `${NODE_INDENT * (data.value?.level - 1) + 9}px`, + top: `${NODE_HEIGHT}px`, + }}); + const nodeHLineClass = computed(() => [ + data.value?.level !== 1 && 'devui-tree-node__hline', + ]); + + const nodeContentClass = computed(() => [ + 'devui-tree-node__content', + data.value?.selected && 'active' + ]); + + const nodeTitleClass = computed(() => [ + 'devui-tree-node__title', + data.value?.disableSelect && 'select-disabled' + ]); + + return { + nodeClass, + nodeStyle, + nodeContentClass, + nodeTitleClass, + nodeVLineClass, + nodeVLineStyle, + nodeHLineClass, + }; +} diff --git a/packages/devui-vue/devui/tree/src/const.ts b/packages/devui-vue/devui/tree/src/const.ts index e9524aaee0..03ce915704 100644 --- a/packages/devui-vue/devui/tree/src/const.ts +++ b/packages/devui-vue/devui/tree/src/const.ts @@ -1 +1,3 @@ export const USE_TREE_TOKEN = 'use-tree-token'; +export const NODE_HEIGHT = 40; +export const NODE_INDENT = 24; 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 fa3ef76074..3ab73b8f66 100644 --- a/packages/devui-vue/devui/tree/src/core/use-core.ts +++ b/packages/devui-vue/devui/tree/src/core/use-core.ts @@ -9,12 +9,13 @@ export default function useCore(data: Ref): IUseCore { return data.value.find((item) => item.id === node.id).level; } - const getChildren = (node: ITreeNode): IInnerTreeNode[] => { + const getChildren = (node: ITreeNode, expanded = false): IInnerTreeNode[] => { let result = []; - const startIndex = data.value.findIndex((item) => item.id === node.id); + const treeData = expanded ? getExpendedTree() : data; + const startIndex = treeData.value.findIndex((item) => item.id === node.id); - for (let i = startIndex + 1; i < data.value.length && getLevel(node) < data.value[i].level; i++) { - result.push(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; 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 76657458d5..653651ccad 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 @@ -27,7 +27,7 @@ export type valueof = T[keyof T]; export interface IUseCore { getLevel: (node: ITreeNode) => number; - getChildren: (node: ITreeNode) => IInnerTreeNode[]; + getChildren: (node: ITreeNode, expanded: boolean) => IInnerTreeNode[]; getExpendedTree: () => ComputedRef; getIndex: (node: ITreeNode) => number; getNode: (node: ITreeNode) => IInnerTreeNode; @@ -68,4 +68,4 @@ export interface IUseToggle { export type IUseTree = { treeData: Ref -} & IUseCore & IUseCheck & IUseDisable & IUseOperate & IUseSelect & IUseToggle; +} & IUseCore & IUseToggle & IUseSelect & IUseCheck & IUseDisable & IUseOperate; diff --git a/packages/devui-vue/devui/tree/src/tree.scss b/packages/devui-vue/devui/tree/src/tree.scss index bec4537fcb..051ee46435 100644 --- a/packages/devui-vue/devui/tree/src/tree.scss +++ b/packages/devui-vue/devui/tree/src/tree.scss @@ -67,7 +67,6 @@ $keyframe-blue: #5e7ce0; .devui-tree-node__content--value-wrapper { display: inline-flex; align-items: center; - height: 30px; width: 100%; .devui-tree-node_loading { @@ -340,3 +339,26 @@ $keyframe-blue: #5e7ce0; cursor: not-allowed !important; background-color: transparent !important; } + +.devui-tree-node { + font-size: 0; +} + +.devui-tree-node, .devui-tree-node__content { + position: relative; +} + +.devui-tree-node__vline { + width: 1px; + background-color: $devui-dividing-line; + position: absolute; +} + +.devui-tree-node__hline { + width: 8px; + height: 1px; + background-color: $devui-dividing-line; + position: absolute; + left: -14px; + top: 50%; +} diff --git a/packages/devui-vue/docs/components/tree/index.md b/packages/devui-vue/docs/components/tree/index.md index ffadb86ab5..ff818d1175 100644 --- a/packages/devui-vue/docs/components/tree/index.md +++ b/packages/devui-vue/docs/components/tree/index.md @@ -1066,8 +1066,32 @@ export default defineComponent({ { label: 'Leaf node 1-2', id: 'node-1-2', - } - ] + children: [ + { + label: 'Leaf node 1-2-1', + id: 'node-1-2-1', + }, + { + label: 'Parent node 1-2-2', + id: 'node-1-2-2', + children: [ + { + label: 'Leaf node 1-2-2-1', + id: 'node-1-2-2-1' + } + ] + }, + { + label: 'Parent node 1-2-3', + id: 'node-1-2-3', + } + ] + }, + { + label: 'Lead node 1-3', + id: 'node-1-3', + }, + ], }, { label: 'Leaf node 2',