diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index ad217d253..554cca191 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -11,6 +11,7 @@ - `n-button` add `tag` prop. - `n-data-table` add `table-layout` prop. - `n-tree` add `block-line` prop. +- `n-tree` support drag & drop. ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index d666eacc3..f73495b15 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -11,6 +11,7 @@ - `n-button` 新增 `tag` 属性 - `n-data-table` 新增 `table-layout` 属性 - `n-tree` 新增 `block-line` 属性 +- `n-tree` 支持拖放 ### Fixes diff --git a/src/tree/demos/enUS/async.demo.md b/src/tree/demos/enUS/async.demo.md index 8931f9fd7..3cb53a22e 100644 --- a/src/tree/demos/enUS/async.demo.md +++ b/src/tree/demos/enUS/async.demo.md @@ -104,7 +104,6 @@ export default { isLeaf: false } ] - this.data = Array.from(this.data) resolve() }, 1000) }) diff --git a/src/tree/demos/zhCN/async.demo.md b/src/tree/demos/zhCN/async.demo.md index 93d2f2726..cd3eab4c0 100644 --- a/src/tree/demos/zhCN/async.demo.md +++ b/src/tree/demos/zhCN/async.demo.md @@ -100,7 +100,6 @@ export default { isLeaf: false } ] - this.data = Array.from(this.data) resolve() }, 1000) }) diff --git a/src/tree/src/Tree.tsx b/src/tree/src/Tree.tsx index a3fa93966..a4df50db7 100644 --- a/src/tree/src/Tree.tsx +++ b/src/tree/src/Tree.tsx @@ -14,7 +14,6 @@ import { import { createTreeMate, flatten, createIndexGetter } from 'treemate' import { useMergedState } from 'vooks' import { VirtualListInst, VVirtualList } from 'vueuc' -import { sleep } from 'seemly' import { useConfig, useTheme } from '../../_mixins' import type { ThemeProps } from '../../_mixins' import { call, warn } from '../../_utils' @@ -268,10 +267,17 @@ export default defineComponent({ return droppingNode.parent }) - watch(toRef(props, 'data'), () => { - loadingKeysRef.value = [] - resetDndState() - }) + // shallow watch data + watch( + toRef(props, 'data'), + () => { + loadingKeysRef.value = [] + resetDndState() + }, + { + deep: false + } + ) watch(toRef(props, 'pattern'), (value) => { if (value) { const [expandedKeysAfterChange, highlightKeys] = keysWithFilter( @@ -531,29 +537,31 @@ export default defineComponent({ nodeKeyToBeExpanded = null } if (!node.shallowLoaded) { - if (props.onLoad) { - if (!loadingKeysRef.value.includes(node.key)) { - loadingKeysRef.value.push(node.key) - } else { - Promise.all([props.onLoad(node.rawNode), sleep(1000)]) - .then(() => { - loadingKeysRef.value.splice( - loadingKeysRef.value.findIndex((key) => key === node.key), - 1 - ) - expand() - }) - .catch(([loadError, _]) => { - console.error(loadError) - resetDragExpandState() - }) + expandTimerId = window.setTimeout(() => { + const { onLoad } = props + if (onLoad) { + if (!loadingKeysRef.value.includes(node.key)) { + loadingKeysRef.value.push(node.key) + onLoad(node.rawNode) + .then(() => { + loadingKeysRef.value.splice( + loadingKeysRef.value.findIndex((key) => key === node.key), + 1 + ) + expand() + }) + .catch((loadError) => { + console.error(loadError) + resetDragExpandState() + }) + } + } else if (__DEV__) { + warn( + 'tree', + 'There is unloaded node in data but props.onLoad is not specified.' + ) } - } else if (__DEV__) { - warn( - 'tree', - 'There is unloaded node in data but props.onLoad is not specified.' - ) - } + }, 1000) } else { expandTimerId = window.setTimeout(() => { expand() @@ -755,28 +763,38 @@ export default defineComponent({ return } - if ( - nodeKeyToBeExpanded !== finalDropNode.key || - (nodeKeyToBeExpanded === null && - finalDropNode.key === draggingNode.key) || - (nodeKeyToBeExpanded !== null && - nodeKeyToBeExpanded === draggingNode.key) - ) { - if (finalDropPosition === 'inside') { - if (props.expandOnDragenter) { - expandDragEnterNode(finalDropNode) - } - // Bailout 4 - if (!finalDropNode.shallowLoaded) { - resetDndState() - return + if (draggingNode.key === finalDropNode.key) { + // don't expand when drag on itself + resetDragExpandState() + } else { + if (nodeKeyToBeExpanded !== finalDropNode.key) { + if (finalDropPosition === 'inside') { + if (props.expandOnDragenter) { + expandDragEnterNode(finalDropNode) + // Bailout 4 + // not try to loading + if ( + !finalDropNode.shallowLoaded && + nodeKeyToBeExpanded !== finalDropNode.key + ) { + resetDndState() + return + } + } else { + // Bailout 5 + // never expands on drag + if (!finalDropNode.shallowLoaded) { + resetDndState() + return + } + } + } else { + resetDragExpandState() } } else { - resetDragExpandState() - } - } else { - if (finalDropPosition !== 'inside') { - resetDragExpandState() + if (finalDropPosition !== 'inside') { + resetDragExpandState() + } } } droppingPositionRef.value = finalDropPosition diff --git a/src/tree/src/TreeNodeSwitcher.tsx b/src/tree/src/TreeNodeSwitcher.tsx index 65c77283c..759caea92 100644 --- a/src/tree/src/TreeNodeSwitcher.tsx +++ b/src/tree/src/TreeNodeSwitcher.tsx @@ -9,18 +9,9 @@ export default defineComponent({ type: String, required: true }, - expanded: { - type: Boolean, - default: false - }, - hide: { - type: Boolean, - default: false - }, - loading: { - type: Boolean, - default: false - }, + expanded: Boolean, + hide: Boolean, + loading: Boolean, onClick: Function as PropType<(e: MouseEvent) => void> }, render () {