Skip to content

Commit

Permalink
fix(Tree): virtual nodes rescroll again when wrapped in css transition (
Browse files Browse the repository at this point in the history
#2399)

* fix(Tree): virtual nodes  rescroll again when wrapped in css transition

* chore: optimize
  • Loading branch information
uyarn authored Jul 28, 2023
1 parent 6a63aae commit dd61a08
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 31 deletions.
48 changes: 37 additions & 11 deletions src/tree/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,13 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
);
const treeRef = useRef(null);

const { visibleData, isVirtual, treeNodeStyle, cursorStyle, handleRowMounted } = useTreeVirtualScroll({
const {
visibleData,
isVirtual,
treeNodeStyle: virtualTreeNodeStyle,
cursorStyle,
handleRowMounted,
} = useTreeVirtualScroll({
treeRef,
scroll,
data: visibleNodes,
Expand Down Expand Up @@ -228,13 +234,35 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
if (renderNode.length <= 0) {
return renderEmpty();
}
if (isVirtual)
return (
<div className={treeClassNames.treeList} style={virtualTreeNodeStyle}>
{renderNode.map((node, index) => (
<TreeItem
ref={nodeList[index]}
key={node.value}
node={node}
empty={empty}
icon={icon}
label={label}
line={line}
transition={transition}
expandOnClickNode={expandOnClickNode}
activable={activable}
operations={operations}
checkProps={checkProps}
disableCheck={disableCheck}
onClick={handleItemClick}
onChange={handleChange}
onTreeItemMounted={handleRowMounted}
isVirtual={isVirtual}
/>
))}
</div>
);

return (
<TransitionGroup
name={transitionNames.treeNode}
className={treeClassNames.treeList}
style={isVirtual ? { ...treeNodeStyle } : null}
>
<TransitionGroup name={transitionNames.treeNode} className={treeClassNames.treeList}>
{renderNode.map((node, index) => (
// https://github.com/reactjs/react-transition-group/issues/668
<CSSTransition
Expand All @@ -245,7 +273,7 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
>
<TreeItem
ref={nodeList[index]}
node={store.getNode(node.value)}
node={node}
empty={empty}
icon={icon}
label={label}
Expand All @@ -258,8 +286,6 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
disableCheck={disableCheck}
onClick={handleItemClick}
onChange={handleChange}
onTreeItemMounted={handleRowMounted}
isVirtual={true}
/>
</CSSTransition>
))}
Expand All @@ -284,14 +310,14 @@ const Tree = forwardRef((props: TreeProps, ref: React.Ref<TreeInstanceFunctions>
[treeClassNames.treeCheckable]: checkable,
[treeClassNames.treeFx]: transition,
[treeClassNames.treeBlockNode]: expandOnClickNode,
[`${treeClassNames.tree}__vscroll`]: isVirtual,
[treeClassNames.treeVscroll]: isVirtual,
})}
style={style}
ref={treeRef}
>
{isVirtual ? (
<>
<div className={`${treeClassNames.tree}__vscroll-cursor`} style={cursorStyle} />
<div className={treeClassNames.treeVscrollCursor} style={cursorStyle} />
{renderItems(visibleData)}
</>
) : (
Expand Down
3 changes: 3 additions & 0 deletions src/tree/hooks/useTreeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export function useTreeConfig() {
loading: `${prefix}-icon-loading ${prefix}-icon-loading-blue`,
toggleEnter: `${tree}__item--enter-active`, // 节点展开动画
toggleLeave: `${tree}__item--leave-active`, // 节点关闭动画
// 虚拟滚动相关
treeVscroll: `${tree}__vscroll`,
treeVscrollCursor: `${tree}__vscroll-cursor`,
};

const transitionNames = {
Expand Down
37 changes: 17 additions & 20 deletions src/tree/hooks/useTreeVirtualScroll.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMemo, useCallback, useEffect, CSSProperties } from 'react';
import { useMemo, useEffect, CSSProperties } from 'react';
import useVirtualScroll from '../../hooks/useVirtualScroll';
import TreeNode from '../../_common/js/tree/tree-node';

Expand Down Expand Up @@ -43,25 +43,22 @@ export default function useTreeVirtualScroll({
data: data || [],
scroll: scrollParams,
});

let lastScrollY = -1;
const onInnerVirtualScroll = useCallback(
(e: WheelEvent) => {
if (!isVirtual) {
return;
}
const target = e.target as HTMLElement;
const top = target.scrollTop;
// 排除横向滚动出发的纵向虚拟滚动计算
if (Math.abs(lastScrollY - top) > 5) {
handleVirtualScroll();
// eslint-disable-next-line react-hooks/exhaustive-deps
lastScrollY = top;
} else {
lastScrollY = -1;
}
},
[isVirtual, data],
);
const onInnerVirtualScroll = (e: WheelEvent) => {
if (!isVirtual) {
return;
}
const target = e.target as HTMLElement;
const top = target.scrollTop;
if (lastScrollY !== top) {
handleVirtualScroll();
// eslint-disable-next-line react-hooks/exhaustive-deps
} else {
lastScrollY = -1;
}
lastScrollY = top;
};

useEffect(() => {
const treeList = treeRef?.current;
Expand All @@ -75,7 +72,7 @@ export default function useTreeVirtualScroll({
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isVirtual, onInnerVirtualScroll, treeRef.current]);
}, [isVirtual, onInnerVirtualScroll]);

const cursorStyle = {
position: 'absolute',
Expand Down

0 comments on commit dd61a08

Please sign in to comment.