feat(tree): drag & drop

This commit is contained in:
07akioni 2021-05-24 10:49:11 +08:00
parent ea32d23d5c
commit b97ea5aa40
6 changed files with 70 additions and 61 deletions

View File

@ -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

View File

@ -11,6 +11,7 @@
- `n-button` 新增 `tag` 属性
- `n-data-table` 新增 `table-layout` 属性
- `n-tree` 新增 `block-line` 属性
- `n-tree` 支持拖放
### Fixes

View File

@ -104,7 +104,6 @@ export default {
isLeaf: false
}
]
this.data = Array.from(this.data)
resolve()
}, 1000)
})

View File

@ -100,7 +100,6 @@ export default {
isLeaf: false
}
]
this.data = Array.from(this.data)
resolve()
}, 1000)
})

View File

@ -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

View File

@ -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 () {