From 96a4ae1d3ecdc920e13c52b0f8f33da2e61e26e5 Mon Sep 17 00:00:00 2001 From: gxuud Date: Fri, 7 Jan 2022 02:06:43 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E8=8A=82=E7=82=B9=E6=8B=96?= =?UTF-8?q?=E6=8B=BD=E5=8A=9F=E8=83=BD-=E9=80=89=E4=B8=AD=E4=B8=8A?= =?UTF-8?q?=E4=B8=AD=E4=B8=8B=E9=80=89=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tree/src/composables/use-draggable.ts | 90 +++++++++++++++++ .../devui-vue/devui/tree/src/tree-types.ts | 17 +++- packages/devui-vue/devui/tree/src/tree.scss | 31 +++++- packages/devui-vue/devui/tree/src/tree.tsx | 25 +++-- packages/devui-vue/devui/tree/src/util.ts | 1 - .../devui-vue/docs/components/tree/index.md | 98 +++++++++++++++++++ 6 files changed, 246 insertions(+), 16 deletions(-) create mode 100644 packages/devui-vue/devui/tree/src/composables/use-draggable.ts diff --git a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts new file mode 100644 index 0000000000..2cecb2e471 --- /dev/null +++ b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts @@ -0,0 +1,90 @@ +import { reactive } from 'vue' +import type { Ref } from 'vue' +import { TreeItem, IDropType, Nullable } from '../tree-types' + +const ACTIVE_NODE = 'devui-tree-node__content--value-wrapper' + +export default function useDraggable( + draggable: boolean, + dropType: IDropType, + node: Ref> +): any { + const dragState = reactive({ + showIndicator: true, + dropType: null, + draggingNode: null, + indicatorTop: 0, + indicatorLeft: 0, + indicatorWidth: 0 + }) + const removeDraggingStyle = (target: Nullable) => { + target + .querySelector(`.${ACTIVE_NODE}`) + ?.classList.remove(...['prev', 'next', 'inner'].map((item) => `devui-drop-${item}`)) + } + const onDragstart = (event: DragEvent, treeNode: TreeItem) => { + // console.log(event, event.target, treeNode) + dragState.draggingNode = event.target + const data = Object.assign({}, treeNode) + event.dataTransfer.setData('Text', JSON.stringify(data)) + } + const onDragover = (event: DragEvent) => { + // console.log(draggable, node.value) + if (draggable) { + event.preventDefault() + event.dataTransfer.dropEffect = 'move' + if (!node) { + return + } + const dropPrev = dropType.dropPrev + const dropNext = dropType.dropNext + const dropInner = dropType.dropInner + + // console.log(node.value); + let innerDropType + + // const treePosition = node.value.getBoundingClientRect() + const prevPercent = dropPrev ? (dropInner ? 0.25 : dropNext ? 0.45 : 1) : -1 + const nextPercent = dropNext ? (dropInner ? 0.75 : dropPrev ? 0.55 : 0) : 1 + const currentTarget = >event.currentTarget + const targetPosition = currentTarget.getBoundingClientRect() + // const treeNodePosition = currentTarget + // .querySelector('.devui-tree-node__title') + // .getBoundingClientRect() + const distance = event.clientY - targetPosition.top + + if (distance < targetPosition.height * prevPercent) { + innerDropType = 'prev' + } else if (distance > targetPosition.height * nextPercent) { + innerDropType = 'next' + } else if (dropInner) { + innerDropType = 'inner' + } else { + innerDropType = 'none' + } + removeDraggingStyle(currentTarget) + if (innerDropType && innerDropType !== 'none') { + currentTarget.querySelector(`.${ACTIVE_NODE}`)?.classList.add(`devui-drop-${innerDropType}`) + } + } + } + const onDragleave = (event: DragEvent) => { + removeDraggingStyle(>event.currentTarget) + } + const onDrop = (event: DragEvent) => { + removeDraggingStyle(>event.currentTarget) + if (!draggable) { + return + } + event.preventDefault() + const transferDataStr = event.dataTransfer.getData('Text') + } + + return { + onDragstart, + onDragover, + onDragleave, + onDrop, + dragState + } +} diff --git a/packages/devui-vue/devui/tree/src/tree-types.ts b/packages/devui-vue/devui/tree/src/tree-types.ts index 58d6d70d93..e8951ba8cf 100644 --- a/packages/devui-vue/devui/tree/src/tree-types.ts +++ b/packages/devui-vue/devui/tree/src/tree-types.ts @@ -12,6 +12,11 @@ export interface TreeItem { children?: TreeData [key: string]: any } +export interface IDropType { + dropPrev?: boolean + dropNext?: boolean + dropInner?: boolean +} export interface SelectType { [key: string]: 'none' | 'half' | 'select' } @@ -36,14 +41,24 @@ export const treeProps = { type: Boolean, default: false }, + draggable: { + type: Boolean, + default: false + }, checkableRelation: { type: String as () => CheckableRelationType, default: 'none', - } + }, + dropType: { + type: Object as PropType, + default: () => ({}), + }, } as const export type TreeProps = ExtractPropTypes +export type Nullable = null | T + export interface TreeRootType { ctx: SetupContext props: TreeProps diff --git a/packages/devui-vue/devui/tree/src/tree.scss b/packages/devui-vue/devui/tree/src/tree.scss index 2ffc16243d..2924182987 100644 --- a/packages/devui-vue/devui/tree/src/tree.scss +++ b/packages/devui-vue/devui/tree/src/tree.scss @@ -13,12 +13,33 @@ $keyframe-blue: #5e7ce0; white-space: nowrap; } +.devui-tree-indicator { + height: 1px; + background-color: $devui-brand; + position: absolute; +} .devui-tree-node { color: $devui-text-weak; line-height: 1.5; white-space: nowrap; position: relative; + .devui-drop { + &-draggable { + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + } + &-inner { + color: $devui-brand; + } + &-prev { + border-top: 1px solid $devui-brand; + } + &-next { + border-bottom: 1px solid $devui-brand; + } + } + .devui-tree-node__content { display: inline-flex; align-items: center; @@ -149,6 +170,12 @@ $keyframe-blue: #5e7ce0; color: #f2b806; } } + &__indent { + display: inline-block; + width: 16px; + height: 16px; + margin-left: 8px; + } .devui-loading-children { display: inline-block; @@ -308,7 +335,3 @@ $keyframe-blue: #5e7ce0; cursor: not-allowed !important; background-color: transparent !important; } - -.devui-tree-node__content { - transition: color $devui-animation-duration-fast $devui-animation-ease-in-smooth, background-color $devui-animation-duration-fast $devui-animation-ease-in-smooth; -} diff --git a/packages/devui-vue/devui/tree/src/tree.tsx b/packages/devui-vue/devui/tree/src/tree.tsx index c75410d5aa..7b87e4ccb0 100644 --- a/packages/devui-vue/devui/tree/src/tree.tsx +++ b/packages/devui-vue/devui/tree/src/tree.tsx @@ -1,6 +1,6 @@ -import { defineComponent, reactive, toRefs, provide } from 'vue' +import { defineComponent, reactive, ref, toRefs, provide } from 'vue' import type { SetupContext } from 'vue' -import { treeProps, TreeProps, TreeItem, TreeRootType } from './tree-types' +import { treeProps, TreeProps, TreeItem, TreeRootType, Nullable } from './tree-types' import { CHECK_CONFIG } from './config' import { preCheckTree, deleteNode, getId } from './util' import Loading from '../../loading/src/service' @@ -11,6 +11,7 @@ import useHighlightNode from './composables/use-highlight' import useChecked from './composables/use-checked' import useLazy from './composables/use-lazy' import useOperate from './composables/use-operate' +import useDraggable from './composables/use-draggable' import IconOpen from './assets/open.svg' import IconClose from './assets/close.svg' import NodeContent from './tree-node-content' @@ -21,20 +22,19 @@ export default defineComponent({ props: treeProps, emits: ['nodeSelected'], setup(props: TreeProps, ctx: SetupContext) { - const { data, checkable, checkableRelation: cbr } = toRefs(reactive({ ...props, data: preCheckTree(props.data) })) + const { data, checkable, draggable, dropType, checkableRelation: cbr } = toRefs(reactive({ ...props, data: preCheckTree(props.data) })) + const node = ref>(null) const { mergeData } = useMergeNode(data.value) const { openedData, toggle } = useToggle(mergeData) const { nodeClassNameReflect, handleInitNodeClassNameReflect, handleClickOnNode } = useHighlightNode() const { lazyNodesReflect, handleInitLazyNodeReflect, getLazyData } = useLazy() const { selected, onNodeClick } = useChecked(cbr, ctx, data.value) const { editStatusReflect, operateIconReflect, handleReflectIdToIcon } = useOperate(data) - + const { onDragstart, onDragover, onDragleave, onDrop } = useDraggable(draggable.value, dropType.value, node); provide('treeRoot', { ctx, props }) - const Indent = () => { - return - } + const renderNode = (item: TreeItem) => { - const { id = '', label, disabled, open, isParent, level, children, addable, editable, deletable } = item + const { id = '', disabled, open, isParent, level, children, addable, editable, deletable } = item handleReflectIdToIcon( id, { @@ -108,7 +108,7 @@ export default defineComponent({ ? open ? : - : + : } @@ -119,12 +119,17 @@ export default defineComponent({
onDragstart(event)} + onDragover={(event: DragEvent) => onDragover(event, item)} + onDragleave={(event: DragEvent) => onDragleave(event)} + onDrop={(event: DragEvent) => onDrop(event, item)} >
handleClickOnNode(id)} > -
+
{ renderFoldIcon(item) } { checkable.value && onNodeClick(item)} disabled={disabled} {...checkState} /> } diff --git a/packages/devui-vue/devui/tree/src/util.ts b/packages/devui-vue/devui/tree/src/util.ts index 9b0917e3a3..6a74ce670e 100644 --- a/packages/devui-vue/devui/tree/src/util.ts +++ b/packages/devui-vue/devui/tree/src/util.ts @@ -20,7 +20,6 @@ export const flatten = (tree: Array, key = 'children'): Array => { const getRandomId = (): string => (Math.random() * 10 ** 9).toString().slice(0,8) const preCheckNodeId = (d: TreeItem, postfixId?: string): TreeItem => { const randomStr = getRandomId() - console.info('randomStr: ', randomStr) return { ...d, id: postfixId ? `${postfixId}_${randomStr}` : randomStr } } export const getId = (id: string): string => { diff --git a/packages/devui-vue/docs/components/tree/index.md b/packages/devui-vue/docs/components/tree/index.md index a3ab18fab8..b64d5f92e1 100644 --- a/packages/devui-vue/docs/components/tree/index.md +++ b/packages/devui-vue/docs/components/tree/index.md @@ -930,3 +930,101 @@ export default defineComponent({ ``` ::: + + +### 可拖拽树 + +:::demo 通过OperableTree的 draggable 属性配置节点的拖拽功能,并支持外部元素拖拽入树。 + +```vue + + + +``` +::: From ca9e2fe91e5f7bdffe49c093137cb7d9edcf5b04 Mon Sep 17 00:00:00 2001 From: gxuud Date: Sun, 9 Jan 2022 23:19:33 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20tree=E6=8B=96=E6=8B=BD=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tree/src/composables/use-draggable.ts | 114 +++++++++++++++--- packages/devui-vue/devui/tree/src/tree.tsx | 8 +- packages/devui-vue/devui/tree/src/util.ts | 3 + 3 files changed, 103 insertions(+), 22 deletions(-) diff --git a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts index 2cecb2e471..3e5757dd1c 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts @@ -1,35 +1,95 @@ -import { reactive } from 'vue' +import { reactive, ref, watch } from 'vue' import type { Ref } from 'vue' import { TreeItem, IDropType, Nullable } from '../tree-types' +import { cloneDeep } from 'lodash-es' const ACTIVE_NODE = 'devui-tree-node__content--value-wrapper' +interface DragState { + dropType?: 'prev' | 'next' | 'inner' + draggingNode?: Nullable +} export default function useDraggable( draggable: boolean, dropType: IDropType, - node: Ref> + node: Ref>, + renderData: Ref, + data: Ref ): any { - const dragState = reactive({ - showIndicator: true, + const dragState = reactive({ dropType: null, draggingNode: null, - indicatorTop: 0, - indicatorLeft: 0, - indicatorWidth: 0 }) + const treeIdMapValue = ref({}) + watch( + () => renderData.value, + () => { + treeIdMapValue.value = renderData.value.reduce((acc, cur) => ({ ...acc, [cur.id]: cur }), {}) + }, + { deep: true, immediate: true } + ) + const removeDraggingStyle = (target: Nullable) => { target .querySelector(`.${ACTIVE_NODE}`) ?.classList.remove(...['prev', 'next', 'inner'].map((item) => `devui-drop-${item}`)) } + + const checkIsParent = (childNodeId: number | string, parentNodeId: number | string) => { + const realParentId = treeIdMapValue.value[childNodeId].parentId + if (realParentId === parentNodeId) { + return true + } else if (realParentId !== undefined) { + return checkIsParent(realParentId, parentNodeId) + } else { + return false + } + } + const handlerDropData = (dragNodeId: string | number, dropNodeId: string | number, dropType?: string) => { + console.log(dragNodeId, dropNodeId); + + const cloneData = cloneDeep(data.value) + let nowDragNode + let nowDropNode + const ergodic = (curr: TreeItem[]) => { + if (!Array.isArray(curr)) return + curr.every((item, index) => { + if (nowDragNode && nowDropNode) { + return false + } + if (item.id === dragNodeId) { + nowDragNode = { target: curr, index } + } else if (item.id === dropNodeId) { + nowDropNode = { target: curr, index } + } + if (!nowDragNode || !nowDropNode) { + ergodic(item.children) + } + return true + }) + } + ergodic(cloneData) + if (nowDragNode && nowDropNode && dropType) { + if (dropType === '') { + + } + nowDropNode.target.unshift( + cloneDeep(nowDragNode.target[nowDragNode.index]) + ) + nowDragNode.target.splice(nowDragNode.index, 1) + } + + return cloneData + } const onDragstart = (event: DragEvent, treeNode: TreeItem) => { - // console.log(event, event.target, treeNode) - dragState.draggingNode = event.target - const data = Object.assign({}, treeNode) + dragState.draggingNode = >event.target + const data = { + type: 'tree-node', + nodeId: treeNode.id + } event.dataTransfer.setData('Text', JSON.stringify(data)) } const onDragover = (event: DragEvent) => { - // console.log(draggable, node.value) if (draggable) { event.preventDefault() event.dataTransfer.dropEffect = 'move' @@ -40,17 +100,12 @@ export default function useDraggable( const dropNext = dropType.dropNext const dropInner = dropType.dropInner - // console.log(node.value); let innerDropType - // const treePosition = node.value.getBoundingClientRect() const prevPercent = dropPrev ? (dropInner ? 0.25 : dropNext ? 0.45 : 1) : -1 const nextPercent = dropNext ? (dropInner ? 0.75 : dropPrev ? 0.55 : 0) : 1 const currentTarget = >event.currentTarget const targetPosition = currentTarget.getBoundingClientRect() - // const treeNodePosition = currentTarget - // .querySelector('.devui-tree-node__title') - // .getBoundingClientRect() const distance = event.clientY - targetPosition.top if (distance < targetPosition.height * prevPercent) { @@ -60,24 +115,47 @@ export default function useDraggable( } else if (dropInner) { innerDropType = 'inner' } else { - innerDropType = 'none' + innerDropType = undefined } removeDraggingStyle(currentTarget) if (innerDropType && innerDropType !== 'none') { currentTarget.querySelector(`.${ACTIVE_NODE}`)?.classList.add(`devui-drop-${innerDropType}`) } + dragState.dropType = innerDropType } } const onDragleave = (event: DragEvent) => { removeDraggingStyle(>event.currentTarget) } - const onDrop = (event: DragEvent) => { + const onDrop = (event: DragEvent, dropNode: TreeItem) => { removeDraggingStyle(>event.currentTarget) if (!draggable) { return } event.preventDefault() const transferDataStr = event.dataTransfer.getData('Text') + if (transferDataStr) { + try { + const transferData = JSON.parse(transferDataStr) + if (typeof transferData === 'object' && transferData.type === 'tree-node') { + const dragNodeId = transferData.nodeId + const isParent = checkIsParent(dropNode.id, dragNodeId) + if (dragNodeId === dropNode.id || isParent) { + return + } + let result + console.log(cloneDeep(data.value)) + + if (dragState.dropType) { + result = handlerDropData(dragNodeId, dropNode.id, dragState.dropType) + } + console.log(result) + data.value = result + } + } catch (e) { + console.log(e) + } + } } return { diff --git a/packages/devui-vue/devui/tree/src/tree.tsx b/packages/devui-vue/devui/tree/src/tree.tsx index 7b87e4ccb0..0f110075d5 100644 --- a/packages/devui-vue/devui/tree/src/tree.tsx +++ b/packages/devui-vue/devui/tree/src/tree.tsx @@ -1,4 +1,4 @@ -import { defineComponent, reactive, ref, toRefs, provide } from 'vue' +import { defineComponent, reactive, ref, toRefs, provide, unref } from 'vue' import type { SetupContext } from 'vue' import { treeProps, TreeProps, TreeItem, TreeRootType, Nullable } from './tree-types' import { CHECK_CONFIG } from './config' @@ -30,11 +30,11 @@ export default defineComponent({ const { lazyNodesReflect, handleInitLazyNodeReflect, getLazyData } = useLazy() const { selected, onNodeClick } = useChecked(cbr, ctx, data.value) const { editStatusReflect, operateIconReflect, handleReflectIdToIcon } = useOperate(data) - const { onDragstart, onDragover, onDragleave, onDrop } = useDraggable(draggable.value, dropType.value, node); + const { onDragstart, onDragover, onDragleave, onDrop } = useDraggable(draggable.value, dropType.value, node, openedData, data); provide('treeRoot', { ctx, props }) const renderNode = (item: TreeItem) => { - const { id = '', disabled, open, isParent, level, children, addable, editable, deletable } = item + const { id = '', disabled, open, isParent, level, children, addable, editable, deletable } = item handleReflectIdToIcon( id, { @@ -120,7 +120,7 @@ export default defineComponent({ class={['devui-tree-node', open && 'devui-tree-node__open']} style={{ paddingLeft: `${24 * (level - 1)}px` }} draggable={draggable.value} - onDragstart={(event: DragEvent) => onDragstart(event)} + onDragstart={(event: DragEvent) => onDragstart(event, item)} onDragover={(event: DragEvent) => onDragover(event, item)} onDragleave={(event: DragEvent) => onDragleave(event)} onDrop={(event: DragEvent) => onDrop(event, item)} diff --git a/packages/devui-vue/devui/tree/src/util.ts b/packages/devui-vue/devui/tree/src/util.ts index 6a74ce670e..c984e8167a 100644 --- a/packages/devui-vue/devui/tree/src/util.ts +++ b/packages/devui-vue/devui/tree/src/util.ts @@ -33,6 +33,9 @@ export const getId = (id: string): string => { export const preCheckTree = (ds: TreeData, postfixId?: string): TreeData => { return ds.map(d => { const dd = preCheckNodeId(d, postfixId) + if (!dd.parentId && postfixId) { + dd.parentId = postfixId + } return d.children ? { ...dd, children: preCheckTree(d.children, dd.id) From 7576b66532e43060091192f660055a328c0e55c9 Mon Sep 17 00:00:00 2001 From: gxuud Date: Mon, 10 Jan 2022 23:30:12 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90tree=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=8B=96=E6=8B=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tree/src/composables/use-draggable.ts | 35 +++++++++++-------- .../tree/src/composables/use-merge-node.ts | 29 +++++++-------- packages/devui-vue/devui/tree/src/tree.tsx | 4 +-- .../devui-vue/docs/components/tree/index.md | 4 +-- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts index 3e5757dd1c..6be2f23ef5 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-draggable.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-draggable.ts @@ -46,8 +46,6 @@ export default function useDraggable( } } const handlerDropData = (dragNodeId: string | number, dropNodeId: string | number, dropType?: string) => { - console.log(dragNodeId, dropNodeId); - const cloneData = cloneDeep(data.value) let nowDragNode let nowDropNode @@ -58,9 +56,9 @@ export default function useDraggable( return false } if (item.id === dragNodeId) { - nowDragNode = { target: curr, index } + nowDragNode = { target: curr, index, item } } else if (item.id === dropNodeId) { - nowDropNode = { target: curr, index } + nowDropNode = { target: curr, index, item } } if (!nowDragNode || !nowDropNode) { ergodic(item.children) @@ -70,14 +68,26 @@ export default function useDraggable( } ergodic(cloneData) if (nowDragNode && nowDropNode && dropType) { - if (dropType === '') { - + const cloneDrapNode = cloneDeep(nowDragNode.target[nowDragNode.index]) + if (dropType === 'prev') { + nowDropNode.target.splice(nowDropNode.index, 0, cloneDrapNode) + } else if (dropType === 'next') { + nowDropNode.target.splice(nowDropNode.index + 1, 0, cloneDrapNode) + } else if (dropType === 'inner') { + const children = nowDropNode.target[nowDropNode.index].children + if (Array.isArray(children)) { + children.unshift(cloneDrapNode) + } else { + nowDropNode.target[nowDropNode.index].children = [cloneDrapNode] + } } - nowDropNode.target.unshift( - cloneDeep(nowDragNode.target[nowDragNode.index]) - ) - nowDragNode.target.splice(nowDragNode.index, 1) + const targetIndex = nowDragNode.target.indexOf(nowDragNode.item) + if (targetIndex !== -1) { + nowDragNode.target.splice(targetIndex, 1) + } + } + console.log(cloneData); return cloneData } @@ -144,16 +154,13 @@ export default function useDraggable( return } let result - console.log(cloneDeep(data.value)) - if (dragState.dropType) { result = handlerDropData(dragNodeId, dropNode.id, dragState.dropType) } - console.log(result) data.value = result } } catch (e) { - console.log(e) + console.error(e) } } } diff --git a/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts b/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts index 705cf07809..ff7a18c7e0 100644 --- a/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts +++ b/packages/devui-vue/devui/tree/src/composables/use-merge-node.ts @@ -1,13 +1,8 @@ -import { ref } from 'vue' +import { Ref, ref, watch } from 'vue' +import { TreeItem } from '../tree-types' -export default function useMergeNode(data: Array): any { - - - const mergeObject = ( - treeItem, - childName = 'children', - labelName = 'label' - ) => { +export default function useMergeNode(data: Ref): any { + const mergeObject = (treeItem, childName = 'children', labelName = 'label') => { const { [childName]: children, [labelName]: label } = treeItem if ( Array.isArray(children) && @@ -17,7 +12,7 @@ export default function useMergeNode(data: Array): any { ) { return mergeObject( Object.assign({}, children[0], { - [labelName]: `${label} \\ ${children[0][labelName]}`, + [labelName]: `${label} \\ ${children[0][labelName]}` }) ) } @@ -41,14 +36,20 @@ export default function useMergeNode(data: Array): any { } return Object.assign({}, currentObject, { [childName]: mergeNode(currentObject[childName], level + 1, childName, labelName), - level: level + 1, + level: level + 1 }) }) } - - const mergeData = ref(mergeNode(data)) + const mergeData = ref(mergeNode(data.value)) + watch( + () => data.value, + () => { + mergeData.value = mergeNode(data.value) + }, + { deep: true } + ) return { - mergeData, + mergeData } } diff --git a/packages/devui-vue/devui/tree/src/tree.tsx b/packages/devui-vue/devui/tree/src/tree.tsx index 0f110075d5..41924cd8f4 100644 --- a/packages/devui-vue/devui/tree/src/tree.tsx +++ b/packages/devui-vue/devui/tree/src/tree.tsx @@ -24,7 +24,7 @@ export default defineComponent({ setup(props: TreeProps, ctx: SetupContext) { const { data, checkable, draggable, dropType, checkableRelation: cbr } = toRefs(reactive({ ...props, data: preCheckTree(props.data) })) const node = ref>(null) - const { mergeData } = useMergeNode(data.value) + const { mergeData } = useMergeNode(data) const { openedData, toggle } = useToggle(mergeData) const { nodeClassNameReflect, handleInitNodeClassNameReflect, handleClickOnNode } = useHighlightNode() const { lazyNodesReflect, handleInitLazyNodeReflect, getLazyData } = useLazy() @@ -129,8 +129,8 @@ export default defineComponent({ class={`devui-tree-node__content ${nodeClassNameReflect.value[id]}`} onClick={() => handleClickOnNode(id)} > + { renderFoldIcon(item) }
- { renderFoldIcon(item) } { checkable.value && onNodeClick(item)} disabled={disabled} {...checkState} /> } { operateIconReflect.value.find(({ id: d }) => id === d).renderIcon(item) } diff --git a/packages/devui-vue/docs/components/tree/index.md b/packages/devui-vue/docs/components/tree/index.md index b64d5f92e1..69458a1808 100644 --- a/packages/devui-vue/docs/components/tree/index.md +++ b/packages/devui-vue/docs/components/tree/index.md @@ -939,9 +939,9 @@ export default defineComponent({ ```vue