mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-21 04:50:14 +08:00
feat(tree): n-tree
's on-load
prop is triggered when the expanded-keys
prop changes in remote
mode (#1429)
* test(dialog): Update dialog component test (#1404) * test(data-table): update test (#1411) * feat(tree): n-tree's on-load prop is triggered when the expanded-keys prop changes in remote mode * feat: optimization * feat: optimization * feat: optimization * feat: optimization * Update src/tree/src/Tree.tsx Co-authored-by: songjianet <1778651752@qq.com> Co-authored-by: 07akioni <07akioni2@gmail.com>
This commit is contained in:
parent
9a922c6a13
commit
9d43c0db36
@ -13,6 +13,10 @@
|
||||
- `n-select` add `menu-props` prop, closes [#1475](https://github.com/TuSimple/naive-ui/issues/1475).
|
||||
- `n-image`'s `toolbar` add close icon, closes [#1412](https://github.com/TuSimple/naive-ui/issues/1412).
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tree`'s `on-load` prop is triggered when the `expanded-keys` prop changes in `remote` mode, closes [#1339](https://github.com/TuSimple/naive-ui/issues/1339).
|
||||
|
||||
## 2.20.0 (2021-10-28)
|
||||
|
||||
### Breaking Changes
|
||||
|
@ -13,6 +13,10 @@
|
||||
- `n-select` 新增 `menu-props` 属性,关闭 [#1475](https://github.com/TuSimple/naive-ui/issues/1475)
|
||||
- `n-image` 的 `toolbar` 增加关闭图标, 关闭 [#1412](https://github.com/TuSimple/naive-ui/issues/1412)
|
||||
|
||||
### Feats
|
||||
|
||||
- `n-tree` 的 `on-load` 属性在 `remote` 模式下 `expanded-keys` 属性改变时被触发, closes [#1339](https://github.com/TuSimple/naive-ui/issues/1339).
|
||||
|
||||
## 2.20.0 (2021-10-28)
|
||||
|
||||
### Breaking Changes
|
||||
|
@ -10,7 +10,8 @@ import {
|
||||
watch,
|
||||
CSSProperties,
|
||||
VNode,
|
||||
nextTick
|
||||
nextTick,
|
||||
watchEffect
|
||||
} from 'vue'
|
||||
import {
|
||||
createTreeMate,
|
||||
@ -80,6 +81,7 @@ export function createTreeMateOptions<T> (
|
||||
}
|
||||
|
||||
type OnUpdateKeys = (value: Key[], option: Array<TreeOption | null>) => void
|
||||
type OnLoad = (node: TreeOption) => Promise<void>
|
||||
|
||||
export const treeSharedProps = {
|
||||
filter: Function as PropType<(pattern: string, node: TreeOption) => boolean>,
|
||||
@ -150,7 +152,7 @@ const treeProps = {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
onLoad: Function as PropType<(node: TreeOption) => Promise<void>>,
|
||||
onLoad: Function as PropType<OnLoad>,
|
||||
cascade: Boolean,
|
||||
selectable: {
|
||||
type: Boolean,
|
||||
@ -319,13 +321,18 @@ export default defineComponent({
|
||||
|
||||
let expandTimerId: number | null = null
|
||||
let nodeKeyToBeExpanded: Key | null = null
|
||||
const uncontrolledHighlightKeySetRef = ref<Set<Key>>(new Set())
|
||||
const uncontrolledHighlightKeySetRef = ref(new Set<Key>())
|
||||
const controlledHighlightKeySetRef = toRef(props, 'internalHighlightKeySet')
|
||||
const mergedHighlightKeySetRef = useMergedState(
|
||||
controlledHighlightKeySetRef,
|
||||
uncontrolledHighlightKeySetRef
|
||||
)
|
||||
const loadingKeysRef = ref<Key[]>([])
|
||||
const loadingKeysRef = ref(new Set<Key>())
|
||||
const expandedNonLoadingKeysRef = computed(() => {
|
||||
return mergedExpandedKeysRef.value.filter(
|
||||
(key) => !loadingKeysRef.value.has(key)
|
||||
)
|
||||
})
|
||||
|
||||
let dragStartX: number = 0
|
||||
const draggingNodeRef = ref<TmNode | null>(null)
|
||||
@ -359,7 +366,7 @@ export default defineComponent({
|
||||
watch(
|
||||
toRef(props, 'data'),
|
||||
() => {
|
||||
loadingKeysRef.value = []
|
||||
loadingKeysRef.value.clear()
|
||||
pendingNodeKeyRef.value = null
|
||||
resetDndState()
|
||||
},
|
||||
@ -386,7 +393,43 @@ export default defineComponent({
|
||||
uncontrolledHighlightKeySetRef.value = new Set()
|
||||
}
|
||||
})
|
||||
|
||||
async function triggerLoading (node: TmNode): Promise<void> {
|
||||
const { onLoad } = props
|
||||
if (!onLoad) {
|
||||
if (__DEV__) {
|
||||
warn(
|
||||
'tree',
|
||||
'There is unloaded node in data but props.onLoad is not specified.'
|
||||
)
|
||||
}
|
||||
return await Promise.resolve()
|
||||
}
|
||||
const { value: loadingKeys } = loadingKeysRef
|
||||
return await new Promise((resolve) => {
|
||||
if (!loadingKeys.has(node.key)) {
|
||||
loadingKeys.add(node.key)
|
||||
onLoad(node.rawNode)
|
||||
.then(() => {
|
||||
loadingKeys.delete(node.key)
|
||||
resolve()
|
||||
})
|
||||
.catch((loadError) => {
|
||||
console.error(loadError)
|
||||
resetDragExpandState()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
watchEffect(() => {
|
||||
const { value: displayTreeMate } = displayTreeMateRef
|
||||
displayTreeMate &&
|
||||
mergedExpandedKeysRef.value?.forEach((key) => {
|
||||
const node = displayTreeMate.getNode(key)
|
||||
if (node && !node.shallowLoaded) {
|
||||
void triggerLoading(node)
|
||||
}
|
||||
})
|
||||
})
|
||||
// animation in progress
|
||||
const aipRef = ref(false)
|
||||
// animation flattened nodes
|
||||
@ -396,7 +439,7 @@ export default defineComponent({
|
||||
// during animation. This will seldom cause wired scrollbar status. It is
|
||||
// fixable and need some changes in vueuc, I've no time so I just leave it
|
||||
// here. Maybe the bug won't be fixed during the life time of the project.
|
||||
watch(mergedExpandedKeysRef, (value, prevValue) => {
|
||||
watch(expandedNonLoadingKeysRef, (value, prevValue) => {
|
||||
if (!props.animated) {
|
||||
void nextTick(syncScrollbar)
|
||||
return
|
||||
@ -728,29 +771,9 @@ export default defineComponent({
|
||||
}
|
||||
if (!node.shallowLoaded) {
|
||||
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.'
|
||||
)
|
||||
}
|
||||
void triggerLoading(node).then(() => {
|
||||
expand()
|
||||
})
|
||||
}, 1000)
|
||||
} else {
|
||||
expandTimerId = window.setTimeout(() => {
|
||||
|
@ -54,8 +54,8 @@ const TreeNode = defineComponent({
|
||||
function handleSwitcherClick (): void {
|
||||
const { tmNode } = props
|
||||
if (NTree.remoteRef.value && !tmNode.isLeaf && !tmNode.shallowLoaded) {
|
||||
if (!NTree.loadingKeysRef.value.includes(tmNode.key)) {
|
||||
NTree.loadingKeysRef.value.push(tmNode.key)
|
||||
if (!NTree.loadingKeysRef.value.has(tmNode.key)) {
|
||||
NTree.loadingKeysRef.value.add(tmNode.key)
|
||||
}
|
||||
const {
|
||||
onLoadRef: { value: onLoad }
|
||||
@ -66,12 +66,7 @@ const TreeNode = defineComponent({
|
||||
NTree.handleSwitcherClick(tmNode)
|
||||
})
|
||||
.finally(() => {
|
||||
NTree.loadingKeysRef.value.splice(
|
||||
NTree.loadingKeysRef.value.findIndex(
|
||||
(key) => key === tmNode.key
|
||||
),
|
||||
1
|
||||
)
|
||||
NTree.loadingKeysRef.value.delete(tmNode.key)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
@ -161,9 +156,7 @@ const TreeNode = defineComponent({
|
||||
pending: useMemo(
|
||||
() => NTree.pendingNodeKeyRef.value === props.tmNode.key
|
||||
),
|
||||
loading: useMemo(() =>
|
||||
NTree.loadingKeysRef.value.includes(props.tmNode.key)
|
||||
),
|
||||
loading: useMemo(() => NTree.loadingKeysRef.value.has(props.tmNode.key)),
|
||||
highlight: useMemo(() =>
|
||||
NTree.highlightKeySetRef.value.has(props.tmNode.key)
|
||||
),
|
||||
|
@ -70,7 +70,7 @@ export interface InternalDropInfo {
|
||||
}
|
||||
|
||||
export interface TreeInjection {
|
||||
loadingKeysRef: Ref<Key[]>
|
||||
loadingKeysRef: Ref<Set<Key>>
|
||||
highlightKeySetRef: Ref<Set<Key>>
|
||||
displayedCheckedKeysRef: Ref<Key[]>
|
||||
displayedIndeterminateKeysRef: Ref<Key[]>
|
||||
|
@ -263,4 +263,45 @@ describe('n-tree', () => {
|
||||
|
||||
expect(wrapper.find('.n-tree-node--disabled').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('should work with `onLoad`', async () => {
|
||||
const onLoad = jest.fn()
|
||||
const wrapper = mount(NTree, {
|
||||
props: {
|
||||
data: [
|
||||
{
|
||||
label: 'test',
|
||||
key: 1,
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
label: '1231',
|
||||
key: 3
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'test',
|
||||
key: 2,
|
||||
disabled: true,
|
||||
children: [
|
||||
{
|
||||
label: '1231',
|
||||
key: 4
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'expanded-keys': [1],
|
||||
remote: true,
|
||||
onLoad: onLoad
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
expect(onLoad).toHaveBeenCalled()
|
||||
wrapper.setProps({ 'expanded-keys': [1, 2] }).then(() => {
|
||||
expect(onLoad).toHaveBeenCalled()
|
||||
})
|
||||
}, 0)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user