Skip to content

Commit daf9227

Browse files
authored
Merge pull request #107 from wsfe/fix/animation-duplicate-key
fix: animation duplicate key
2 parents 27f87ac + 48d7df5 commit daf9227

9 files changed

+64
-61
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@wsfe/vue-tree",
3-
"version": "4.1.0",
3+
"version": "4.1.1",
44
"types": "./types",
55
"description": "A vue tree component using virtual list.",
66
"main": "./dist/vue-tree.umd.js",

src/components/Tree.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ const {
361361
blockLength,
362362
topSpaceHeight,
363363
bottomSpaceHeight,
364+
renderStart,
364365
resetSpaceHeights,
365366
updateRender,
366367
updateBlockNodes,
@@ -369,7 +370,7 @@ const {
369370
scrollTo,
370371
} = useVirtualList(nonReactive, props)
371372
372-
const expandAnimation = useExpandAnimation(renderNodes, props)
373+
const expandAnimation = useExpandAnimation(renderNodes, renderStart, props)
373374
374375
const {
375376
unloadCheckedNodes,

src/components/TreeSearch.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ function search(keyword1?: string): Promise<void> {
216216
resolve()
217217
}
218218
}
219-
}, props.searchDebounceTime)
219+
}, props.searchDebounceTime) as unknown as number
220220
})
221221
}
222222
//#endregion Public API

src/hooks/useExpandAnimation.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@ type IUseExpandAnimationProps = Required<Pick<TreeProps,
77
'animation'
88
>>
99

10-
export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseExpandAnimationProps) => {
10+
export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, renderStartRef: Ref<number>, props: IUseExpandAnimationProps) => {
1111
const expandAnimationStart = ref(false)
1212
const expandAnimationReady = ref(false)
1313
const expandNodeIndex = ref(-1)
1414
const expandNodeLevel = ref(-1)
1515
const expandNodeCurrentState = ref(false)
1616
const expandNodeNextState = ref(false)
1717

18+
const expandRenderStart = ref(0)
1819
const expandTopNodes = ref<TreeNode[]>([])
1920
const expandMiddleNodes = ref<TreeNode[]>([])
2021
const expandBottomNodes = ref<TreeNode[]>([])
@@ -25,6 +26,7 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
2526
expandNodeIndex.value = -1
2627
expandNodeLevel.value = -1
2728

29+
expandRenderStart.value = 0
2830
expandTopNodes.value = []
2931
expandMiddleNodes.value = []
3032
expandBottomNodes.value = []
@@ -34,7 +36,8 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
3436
const nodeToExpandLevel = expandNodeLevel.value
3537
const middleNodes: TreeNode[] = []
3638
const renderNodesLength = renderNodesRef.value.length
37-
for (let i = expandNodeIndex.value + 1; i < renderNodesLength; i++) {
39+
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
40+
for (let i = expandNodeIndex.value - expandRenderStartDiff + 1; i < renderNodesLength; i++) {
3841
if (renderNodesRef.value[i]._level > nodeToExpandLevel) {
3942
middleNodes.push(renderNodesRef.value[i])
4043
} else break
@@ -54,6 +57,7 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
5457
expandAnimationStart.value = true
5558
expandNodeCurrentState.value = nodeToExpand.expand
5659
expandNodeNextState.value = !nodeToExpand.expand
60+
expandRenderStart.value = renderStartRef.value
5761

5862
if (expandNodeNextState.value) {
5963
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value + 1)
@@ -74,11 +78,12 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
7478
if (expandNodeIndex.value === -1) return
7579

7680
nextTick(() => {
77-
expandTopNodes.value = renderNodesRef.value.slice(0, expandNodeIndex.value + 1)
81+
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
82+
expandTopNodes.value = renderNodesRef.value.slice(0, expandNodeIndex.value - expandRenderStartDiff + 1)
7883
if (expandNodeNextState.value) {
7984
updateMiddleNodes()
8085
} else {
81-
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value + 1)
86+
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value - expandRenderStartDiff + 1)
8287
}
8388
expandAnimationReady.value = true
8489
nextTick(() => {

tsconfig.tsbuildinfo

+1-1
Large diffs are not rendered by default.

types/components/Tree.vue.d.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
174174
loadRootNodes: () => Promise<void>;
175175
updateNode: (key: TreeNodeKeyType, newNode: import("../store/tree-node").ITreeNodeOptions) => void;
176176
updateNodes: (newNodes: import("../store/tree-node").ITreeNodeOptions[]) => void;
177-
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
177+
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
178178
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
179179
[x: string]: (...args: any[]) => void;
180180
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeProps>, {
@@ -207,31 +207,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
207207
renderNodeAmount: number;
208208
bufferNodeAmount: number;
209209
}>>>, {
210-
keyField: string;
211-
ignoreMode: "none" | "parents" | "children";
212-
filteredNodeCheckable: boolean;
213-
cascade: boolean;
214-
defaultExpandAll: boolean;
215-
expandOnFilter: boolean;
216-
titleField: string;
217-
checkable: boolean;
218-
selectable: boolean;
219-
unselectOnClick: boolean;
220-
disableAll: boolean;
221-
draggable: boolean;
222-
droppable: boolean;
223-
nodeIndent: number;
224210
data: AnyPropsArrayType;
225211
emptyText: string;
212+
selectable: boolean;
213+
checkable: boolean;
226214
separator: string;
215+
ignoreMode: "none" | "parents" | "children";
216+
titleField: string;
217+
keyField: string;
227218
showUnloadCheckedNodes: boolean;
228219
unloadDataList: AnyPropsArrayType;
220+
filteredNodeCheckable: boolean;
221+
cascade: boolean;
229222
enableLeafOnly: boolean;
223+
disableAll: boolean;
224+
defaultExpandAll: boolean;
230225
defaultExpandedKeys: TreeNodeKeyType[];
231226
expandedKeys: TreeNodeKeyType[];
227+
draggable: boolean;
228+
droppable: boolean;
232229
beforeDropMethod: (dragKey: TreeNodeKeyType, dropKey: TreeNodeKeyType, hoverPart: dragHoverPartEnum) => boolean;
233230
autoLoad: boolean;
231+
expandOnFilter: boolean;
232+
unselectOnClick: boolean;
234233
loading: boolean;
234+
nodeIndent: number;
235235
renderNodeAmount: number;
236236
nodeMinHeight: number;
237237
bufferNodeAmount: number;

types/components/TreeDrop.vue.d.ts

+18-21
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export declare const DEFAULT_TREE_DROP_PROPS: {
3030
transfer: boolean;
3131
dropdownWidthFixed: boolean;
3232
searchPlaceholder: string;
33-
/** 处理树数据更新 */
3433
showCheckAll: boolean;
3534
showCheckedButton: boolean;
3635
checkedButtonText: string;
@@ -76,7 +75,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
7675
transfer: boolean;
7776
dropdownWidthFixed: boolean;
7877
searchPlaceholder: string;
79-
/** 处理树数据更新 */
8078
showCheckAll: boolean;
8179
showCheckedButton: boolean;
8280
checkedButtonText: string;
@@ -114,6 +112,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
114112
renderNodeAmount: number;
115113
bufferNodeAmount: number;
116114
}>, {
115+
search: (keyword1?: string | undefined) => Promise<void>;
116+
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
117117
setData: (data: import("../types").AnyPropsArrayType) => void;
118118
setChecked: (key: TreeNodeKeyType, value: boolean) => void;
119119
setCheckedKeys: (keys: TreeNodeKeyType[], value: boolean) => void;
@@ -141,15 +141,13 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
141141
append: (insertedNode: TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: TreeNodeKeyType) => TreeNode | null;
142142
prepend: (insertedNode: TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: TreeNodeKeyType) => TreeNode | null;
143143
remove: (removedKey: TreeNodeKeyType) => TreeNode | null;
144-
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
145144
showCheckedNodes: (showUnloadCheckedNodes?: boolean | undefined) => void;
146145
loadRootNodes: () => Promise<void>;
147146
updateNode: (key: TreeNodeKeyType, newNode: import("../store/tree-node.js").ITreeNodeOptions) => void;
148147
updateNodes: (newNodes: import("../store/tree-node.js").ITreeNodeOptions[]) => void;
149-
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
148+
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
150149
clearKeyword: () => void;
151150
getKeyword: () => string;
152-
search: (keyword1?: string | undefined) => Promise<void>;
153151
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
154152
[x: string]: (...args: any[]) => void;
155153
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeDropProps>, {
@@ -160,7 +158,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
160158
transfer: boolean;
161159
dropdownWidthFixed: boolean;
162160
searchPlaceholder: string;
163-
/** 处理树数据更新 */
164161
showCheckAll: boolean;
165162
showCheckedButton: boolean;
166163
checkedButtonText: string;
@@ -198,31 +195,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
198195
renderNodeAmount: number;
199196
bufferNodeAmount: number;
200197
}>>>, {
201-
keyField: string;
202-
ignoreMode: "none" | "parents" | "children";
203-
filteredNodeCheckable: boolean;
204-
cascade: boolean;
205-
defaultExpandAll: boolean;
206-
expandOnFilter: boolean;
207-
titleField: string;
208-
checkable: boolean;
209-
selectable: boolean;
210-
unselectOnClick: boolean;
211-
disableAll: boolean;
212-
draggable: boolean;
213-
droppable: boolean;
214-
nodeIndent: number;
215198
data: import("../types").AnyPropsArrayType;
216199
emptyText: string;
200+
selectable: boolean;
201+
checkable: boolean;
217202
separator: string;
203+
ignoreMode: "none" | "parents" | "children";
204+
titleField: string;
205+
keyField: string;
218206
showUnloadCheckedNodes: boolean;
219207
unloadDataList: import("../types").AnyPropsArrayType;
208+
filteredNodeCheckable: boolean;
209+
cascade: boolean;
220210
enableLeafOnly: boolean;
211+
disableAll: boolean;
212+
defaultExpandAll: boolean;
221213
defaultExpandedKeys: TreeNodeKeyType[];
222214
expandedKeys: TreeNodeKeyType[];
215+
draggable: boolean;
216+
droppable: boolean;
223217
beforeDropMethod: (dragKey: TreeNodeKeyType, dropKey: TreeNodeKeyType, hoverPart: import("../constants").dragHoverPartEnum) => boolean;
224218
autoLoad: boolean;
219+
expandOnFilter: boolean;
220+
unselectOnClick: boolean;
225221
loading: boolean;
222+
nodeIndent: number;
226223
renderNodeAmount: number;
227224
nodeMinHeight: number;
228225
bufferNodeAmount: number;
@@ -238,7 +235,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
238235
dropHeight: number;
239236
dropDisabled: boolean;
240237
clearable: boolean;
241-
placement: "bottom-start" | "bottom-end" | "bottom" | "top-start" | "top-end" | "top";
238+
placement: "top" | "bottom" | "bottom-start" | "bottom-end" | "top-start" | "top-end";
242239
transfer: boolean;
243240
dropdownWidthFixed: boolean;
244241
}, {}>, Partial<Record<NonNullable<string | number>, (_: any) => any>> & {

types/components/TreeSearch.vue.d.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
103103
clearKeyword: () => void;
104104
getKeyword: () => string;
105105
search: (keyword1?: string) => Promise<void>;
106+
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
106107
setData: (data: import("..").AnyPropsArrayType) => void;
107108
setChecked: (key: import("..").TreeNodeKeyType, value: boolean) => void;
108109
setCheckedKeys: (keys: import("..").TreeNodeKeyType[], value: boolean) => void;
@@ -130,12 +131,11 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
130131
append: (insertedNode: import("..").TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: import("..").TreeNodeKeyType) => TreeNode | null;
131132
prepend: (insertedNode: import("..").TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: import("..").TreeNodeKeyType) => TreeNode | null;
132133
remove: (removedKey: import("..").TreeNodeKeyType) => TreeNode | null;
133-
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
134134
showCheckedNodes: (showUnloadCheckedNodes?: boolean | undefined) => void;
135135
loadRootNodes: () => Promise<void>;
136136
updateNode: (key: import("..").TreeNodeKeyType, newNode: import("../store/tree-node.js").ITreeNodeOptions) => void;
137137
updateNodes: (newNodes: import("../store/tree-node.js").ITreeNodeOptions[]) => void;
138-
scrollTo: (key: import("..").TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
138+
scrollTo: (key: import("..").TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
139139
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
140140
[x: string]: (...args: any[]) => void;
141141
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeSearchProps>, {
@@ -177,31 +177,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
177177
renderNodeAmount: number;
178178
bufferNodeAmount: number;
179179
}>>>, {
180-
keyField: string;
181-
ignoreMode: "none" | "parents" | "children";
182-
filteredNodeCheckable: boolean;
183-
cascade: boolean;
184-
defaultExpandAll: boolean;
185-
expandOnFilter: boolean;
186-
titleField: string;
187-
checkable: boolean;
188-
selectable: boolean;
189-
unselectOnClick: boolean;
190-
disableAll: boolean;
191-
draggable: boolean;
192-
droppable: boolean;
193-
nodeIndent: number;
194180
data: import("..").AnyPropsArrayType;
195181
emptyText: string;
182+
selectable: boolean;
183+
checkable: boolean;
196184
separator: string;
185+
ignoreMode: "none" | "parents" | "children";
186+
titleField: string;
187+
keyField: string;
197188
showUnloadCheckedNodes: boolean;
198189
unloadDataList: import("..").AnyPropsArrayType;
190+
filteredNodeCheckable: boolean;
191+
cascade: boolean;
199192
enableLeafOnly: boolean;
193+
disableAll: boolean;
194+
defaultExpandAll: boolean;
200195
defaultExpandedKeys: import("..").TreeNodeKeyType[];
201196
expandedKeys: import("..").TreeNodeKeyType[];
197+
draggable: boolean;
198+
droppable: boolean;
202199
beforeDropMethod: (dragKey: import("..").TreeNodeKeyType, dropKey: import("..").TreeNodeKeyType, hoverPart: import("../constants").dragHoverPartEnum) => boolean;
203200
autoLoad: boolean;
201+
expandOnFilter: boolean;
202+
unselectOnClick: boolean;
204203
loading: boolean;
204+
nodeIndent: number;
205205
renderNodeAmount: number;
206206
nodeMinHeight: number;
207207
bufferNodeAmount: number;

types/hooks/useExpandAnimation.d.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Ref } from "vue";
22
import { TreeNode } from "../store";
33
import { TreeProps } from "../components/Tree.vue";
44
type IUseExpandAnimationProps = Required<Pick<TreeProps, 'keyField' | 'animation'>>;
5-
export declare const useExpandAnimation: (renderNodesRef: Ref<TreeNode[]>, props: IUseExpandAnimationProps) => {
5+
export declare const useExpandAnimation: (renderNodesRef: Ref<TreeNode[]>, renderStartRef: Ref<number>, props: IUseExpandAnimationProps) => {
66
ready: Ref<boolean>;
77
currentExpandState: Ref<boolean>;
88
topNodes: Ref<{

0 commit comments

Comments
 (0)