Skip to content

Commit

Permalink
Merge pull request #107 from wsfe/fix/animation-duplicate-key
Browse files Browse the repository at this point in the history
fix: animation duplicate key
  • Loading branch information
ChuChencheng authored Sep 21, 2024
2 parents 27f87ac + 48d7df5 commit daf9227
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 61 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@wsfe/vue-tree",
"version": "4.1.0",
"version": "4.1.1",
"types": "./types",
"description": "A vue tree component using virtual list.",
"main": "./dist/vue-tree.umd.js",
Expand Down
3 changes: 2 additions & 1 deletion src/components/Tree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ const {
blockLength,
topSpaceHeight,
bottomSpaceHeight,
renderStart,
resetSpaceHeights,
updateRender,
updateBlockNodes,
Expand All @@ -369,7 +370,7 @@ const {
scrollTo,
} = useVirtualList(nonReactive, props)
const expandAnimation = useExpandAnimation(renderNodes, props)
const expandAnimation = useExpandAnimation(renderNodes, renderStart, props)
const {
unloadCheckedNodes,
Expand Down
2 changes: 1 addition & 1 deletion src/components/TreeSearch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function search(keyword1?: string): Promise<void> {
resolve()
}
}
}, props.searchDebounceTime)
}, props.searchDebounceTime) as unknown as number
})
}
//#endregion Public API
Expand Down
13 changes: 9 additions & 4 deletions src/hooks/useExpandAnimation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ type IUseExpandAnimationProps = Required<Pick<TreeProps,
'animation'
>>

export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseExpandAnimationProps) => {
export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, renderStartRef: Ref<number>, props: IUseExpandAnimationProps) => {
const expandAnimationStart = ref(false)
const expandAnimationReady = ref(false)
const expandNodeIndex = ref(-1)
const expandNodeLevel = ref(-1)
const expandNodeCurrentState = ref(false)
const expandNodeNextState = ref(false)

const expandRenderStart = ref(0)
const expandTopNodes = ref<TreeNode[]>([])
const expandMiddleNodes = ref<TreeNode[]>([])
const expandBottomNodes = ref<TreeNode[]>([])
Expand All @@ -25,6 +26,7 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
expandNodeIndex.value = -1
expandNodeLevel.value = -1

expandRenderStart.value = 0
expandTopNodes.value = []
expandMiddleNodes.value = []
expandBottomNodes.value = []
Expand All @@ -34,7 +36,8 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
const nodeToExpandLevel = expandNodeLevel.value
const middleNodes: TreeNode[] = []
const renderNodesLength = renderNodesRef.value.length
for (let i = expandNodeIndex.value + 1; i < renderNodesLength; i++) {
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
for (let i = expandNodeIndex.value - expandRenderStartDiff + 1; i < renderNodesLength; i++) {
if (renderNodesRef.value[i]._level > nodeToExpandLevel) {
middleNodes.push(renderNodesRef.value[i])
} else break
Expand All @@ -54,6 +57,7 @@ export const useExpandAnimation = (renderNodesRef: Ref<TreeNode[]>, props: IUseE
expandAnimationStart.value = true
expandNodeCurrentState.value = nodeToExpand.expand
expandNodeNextState.value = !nodeToExpand.expand
expandRenderStart.value = renderStartRef.value

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

nextTick(() => {
expandTopNodes.value = renderNodesRef.value.slice(0, expandNodeIndex.value + 1)
const expandRenderStartDiff = renderStartRef.value - expandRenderStart.value
expandTopNodes.value = renderNodesRef.value.slice(0, expandNodeIndex.value - expandRenderStartDiff + 1)
if (expandNodeNextState.value) {
updateMiddleNodes()
} else {
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value + 1)
expandBottomNodes.value = renderNodesRef.value.slice(expandNodeIndex.value - expandRenderStartDiff + 1)
}
expandAnimationReady.value = true
nextTick(() => {
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.tsbuildinfo

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions types/components/Tree.vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
loadRootNodes: () => Promise<void>;
updateNode: (key: TreeNodeKeyType, newNode: import("../store/tree-node").ITreeNodeOptions) => void;
updateNodes: (newNodes: import("../store/tree-node").ITreeNodeOptions[]) => void;
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
[x: string]: (...args: any[]) => void;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeProps>, {
Expand Down Expand Up @@ -207,31 +207,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
renderNodeAmount: number;
bufferNodeAmount: number;
}>>>, {
keyField: string;
ignoreMode: "none" | "parents" | "children";
filteredNodeCheckable: boolean;
cascade: boolean;
defaultExpandAll: boolean;
expandOnFilter: boolean;
titleField: string;
checkable: boolean;
selectable: boolean;
unselectOnClick: boolean;
disableAll: boolean;
draggable: boolean;
droppable: boolean;
nodeIndent: number;
data: AnyPropsArrayType;
emptyText: string;
selectable: boolean;
checkable: boolean;
separator: string;
ignoreMode: "none" | "parents" | "children";
titleField: string;
keyField: string;
showUnloadCheckedNodes: boolean;
unloadDataList: AnyPropsArrayType;
filteredNodeCheckable: boolean;
cascade: boolean;
enableLeafOnly: boolean;
disableAll: boolean;
defaultExpandAll: boolean;
defaultExpandedKeys: TreeNodeKeyType[];
expandedKeys: TreeNodeKeyType[];
draggable: boolean;
droppable: boolean;
beforeDropMethod: (dragKey: TreeNodeKeyType, dropKey: TreeNodeKeyType, hoverPart: dragHoverPartEnum) => boolean;
autoLoad: boolean;
expandOnFilter: boolean;
unselectOnClick: boolean;
loading: boolean;
nodeIndent: number;
renderNodeAmount: number;
nodeMinHeight: number;
bufferNodeAmount: number;
Expand Down
39 changes: 18 additions & 21 deletions types/components/TreeDrop.vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export declare const DEFAULT_TREE_DROP_PROPS: {
transfer: boolean;
dropdownWidthFixed: boolean;
searchPlaceholder: string;
/** 处理树数据更新 */
showCheckAll: boolean;
showCheckedButton: boolean;
checkedButtonText: string;
Expand Down Expand Up @@ -76,7 +75,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
transfer: boolean;
dropdownWidthFixed: boolean;
searchPlaceholder: string;
/** 处理树数据更新 */
showCheckAll: boolean;
showCheckedButton: boolean;
checkedButtonText: string;
Expand Down Expand Up @@ -114,6 +112,8 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
renderNodeAmount: number;
bufferNodeAmount: number;
}>, {
search: (keyword1?: string | undefined) => Promise<void>;
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
setData: (data: import("../types").AnyPropsArrayType) => void;
setChecked: (key: TreeNodeKeyType, value: boolean) => void;
setCheckedKeys: (keys: TreeNodeKeyType[], value: boolean) => void;
Expand Down Expand Up @@ -141,15 +141,13 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
append: (insertedNode: TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: TreeNodeKeyType) => TreeNode | null;
prepend: (insertedNode: TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: TreeNodeKeyType) => TreeNode | null;
remove: (removedKey: TreeNodeKeyType) => TreeNode | null;
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
showCheckedNodes: (showUnloadCheckedNodes?: boolean | undefined) => void;
loadRootNodes: () => Promise<void>;
updateNode: (key: TreeNodeKeyType, newNode: import("../store/tree-node.js").ITreeNodeOptions) => void;
updateNodes: (newNodes: import("../store/tree-node.js").ITreeNodeOptions[]) => void;
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
scrollTo: (key: TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
clearKeyword: () => void;
getKeyword: () => string;
search: (keyword1?: string | undefined) => Promise<void>;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
[x: string]: (...args: any[]) => void;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeDropProps>, {
Expand All @@ -160,7 +158,6 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
transfer: boolean;
dropdownWidthFixed: boolean;
searchPlaceholder: string;
/** 处理树数据更新 */
showCheckAll: boolean;
showCheckedButton: boolean;
checkedButtonText: string;
Expand Down Expand Up @@ -198,31 +195,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
renderNodeAmount: number;
bufferNodeAmount: number;
}>>>, {
keyField: string;
ignoreMode: "none" | "parents" | "children";
filteredNodeCheckable: boolean;
cascade: boolean;
defaultExpandAll: boolean;
expandOnFilter: boolean;
titleField: string;
checkable: boolean;
selectable: boolean;
unselectOnClick: boolean;
disableAll: boolean;
draggable: boolean;
droppable: boolean;
nodeIndent: number;
data: import("../types").AnyPropsArrayType;
emptyText: string;
selectable: boolean;
checkable: boolean;
separator: string;
ignoreMode: "none" | "parents" | "children";
titleField: string;
keyField: string;
showUnloadCheckedNodes: boolean;
unloadDataList: import("../types").AnyPropsArrayType;
filteredNodeCheckable: boolean;
cascade: boolean;
enableLeafOnly: boolean;
disableAll: boolean;
defaultExpandAll: boolean;
defaultExpandedKeys: TreeNodeKeyType[];
expandedKeys: TreeNodeKeyType[];
draggable: boolean;
droppable: boolean;
beforeDropMethod: (dragKey: TreeNodeKeyType, dropKey: TreeNodeKeyType, hoverPart: import("../constants").dragHoverPartEnum) => boolean;
autoLoad: boolean;
expandOnFilter: boolean;
unselectOnClick: boolean;
loading: boolean;
nodeIndent: number;
renderNodeAmount: number;
nodeMinHeight: number;
bufferNodeAmount: number;
Expand All @@ -238,7 +235,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
dropHeight: number;
dropDisabled: boolean;
clearable: boolean;
placement: "bottom-start" | "bottom-end" | "bottom" | "top-start" | "top-end" | "top";
placement: "top" | "bottom" | "bottom-start" | "bottom-end" | "top-start" | "top-end";
transfer: boolean;
dropdownWidthFixed: boolean;
}, {}>, Partial<Record<NonNullable<string | number>, (_: any) => any>> & {
Expand Down
32 changes: 16 additions & 16 deletions types/components/TreeSearch.vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
clearKeyword: () => void;
getKeyword: () => string;
search: (keyword1?: string) => Promise<void>;
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
setData: (data: import("..").AnyPropsArrayType) => void;
setChecked: (key: import("..").TreeNodeKeyType, value: boolean) => void;
setCheckedKeys: (keys: import("..").TreeNodeKeyType[], value: boolean) => void;
Expand Down Expand Up @@ -130,12 +131,11 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
append: (insertedNode: import("..").TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: import("..").TreeNodeKeyType) => TreeNode | null;
prepend: (insertedNode: import("..").TreeNodeKeyType | import("../store/tree-node.js").ITreeNodeOptions, parentKey: import("..").TreeNodeKeyType) => TreeNode | null;
remove: (removedKey: import("..").TreeNodeKeyType) => TreeNode | null;
filter: (keyword: string, filterMethod?: import("../store/tree-store.js").FilterFunctionType | undefined) => void;
showCheckedNodes: (showUnloadCheckedNodes?: boolean | undefined) => void;
loadRootNodes: () => Promise<void>;
updateNode: (key: import("..").TreeNodeKeyType, newNode: import("../store/tree-node.js").ITreeNodeOptions) => void;
updateNodes: (newNodes: import("../store/tree-node.js").ITreeNodeOptions[]) => void;
scrollTo: (key: import("..").TreeNodeKeyType, verticalPosition?: number | "bottom" | "top" | "center") => void;
scrollTo: (key: import("..").TreeNodeKeyType, verticalPosition?: number | "top" | "center" | "bottom") => void;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
[x: string]: (...args: any[]) => void;
}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<TreeSearchProps>, {
Expand Down Expand Up @@ -177,31 +177,31 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
renderNodeAmount: number;
bufferNodeAmount: number;
}>>>, {
keyField: string;
ignoreMode: "none" | "parents" | "children";
filteredNodeCheckable: boolean;
cascade: boolean;
defaultExpandAll: boolean;
expandOnFilter: boolean;
titleField: string;
checkable: boolean;
selectable: boolean;
unselectOnClick: boolean;
disableAll: boolean;
draggable: boolean;
droppable: boolean;
nodeIndent: number;
data: import("..").AnyPropsArrayType;
emptyText: string;
selectable: boolean;
checkable: boolean;
separator: string;
ignoreMode: "none" | "parents" | "children";
titleField: string;
keyField: string;
showUnloadCheckedNodes: boolean;
unloadDataList: import("..").AnyPropsArrayType;
filteredNodeCheckable: boolean;
cascade: boolean;
enableLeafOnly: boolean;
disableAll: boolean;
defaultExpandAll: boolean;
defaultExpandedKeys: import("..").TreeNodeKeyType[];
expandedKeys: import("..").TreeNodeKeyType[];
draggable: boolean;
droppable: boolean;
beforeDropMethod: (dragKey: import("..").TreeNodeKeyType, dropKey: import("..").TreeNodeKeyType, hoverPart: import("../constants").dragHoverPartEnum) => boolean;
autoLoad: boolean;
expandOnFilter: boolean;
unselectOnClick: boolean;
loading: boolean;
nodeIndent: number;
renderNodeAmount: number;
nodeMinHeight: number;
bufferNodeAmount: number;
Expand Down
2 changes: 1 addition & 1 deletion types/hooks/useExpandAnimation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Ref } from "vue";
import { TreeNode } from "../store";
import { TreeProps } from "../components/Tree.vue";
type IUseExpandAnimationProps = Required<Pick<TreeProps, 'keyField' | 'animation'>>;
export declare const useExpandAnimation: (renderNodesRef: Ref<TreeNode[]>, props: IUseExpandAnimationProps) => {
export declare const useExpandAnimation: (renderNodesRef: Ref<TreeNode[]>, renderStartRef: Ref<number>, props: IUseExpandAnimationProps) => {
ready: Ref<boolean>;
currentExpandState: Ref<boolean>;
topNodes: Ref<{
Expand Down

0 comments on commit daf9227

Please sign in to comment.