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:
XieZongChen 2021-10-31 11:47:07 -05:00 committed by GitHub
parent 9a922c6a13
commit 9d43c0db36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 42 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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