Skip to content

Commit 9aeadaf

Browse files
committed
perf: tree, close #5551
1 parent 53b4c5d commit 9aeadaf

File tree

11 files changed

+267
-208
lines changed

11 files changed

+267
-208
lines changed

components/tree-select/index.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import PropTypes from '../_util/vue-types';
1616
import useConfigInject from '../_util/hooks/useConfigInject';
1717
import devWarning from '../vc-util/devWarning';
1818
import getIcons from '../select/utils/iconUtil';
19+
import type { SwitcherIconProps } from '../tree/utils/iconUtil';
1920
import renderSwitcherIcon from '../tree/utils/iconUtil';
20-
import type { AntTreeNodeProps } from '../tree/Tree';
2121
import { warning } from '../vc-util/warning';
2222
import { flattenChildren } from '../_util/props-util';
2323
import { useInjectFormItemContext } from '../form/FormItemContext';
@@ -239,7 +239,7 @@ const TreeSelect = defineComponent({
239239
multiple={multiple}
240240
removeIcon={removeIcon}
241241
clearIcon={clearIcon}
242-
switcherIcon={(nodeProps: AntTreeNodeProps) =>
242+
switcherIcon={(nodeProps: SwitcherIconProps) =>
243243
renderSwitcherIcon(treePrefixCls.value, switcherIcon, treeLine, nodeProps)
244244
}
245245
showTreeIcon={treeIcon as any}

components/tree/Tree.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { DataNode, EventDataNode, FieldNames, Key } from '../vc-tree/interf
99
import type { TreeNodeProps } from '../vc-tree/props';
1010
import { treeProps as vcTreeProps } from '../vc-tree/props';
1111
import useConfigInject from '../_util/hooks/useConfigInject';
12+
import type { SwitcherIconProps } from './utils/iconUtil';
1213
import renderSwitcherIcon from './utils/iconUtil';
1314
import dropIndicatorRender from './utils/dropIndicator';
1415
import devWarning from '../vc-util/devWarning';
@@ -229,7 +230,7 @@ export default defineComponent({
229230
icon,
230231
itemHeight,
231232
};
232-
233+
const children = slots.default ? filterEmpty(slots.default()) : undefined;
233234
return (
234235
<VcTree
235236
{...newProps}
@@ -249,7 +250,7 @@ export default defineComponent({
249250
direction={direction.value}
250251
checkable={checkable}
251252
selectable={selectable}
252-
switcherIcon={(nodeProps: AntTreeNodeProps) =>
253+
switcherIcon={(nodeProps: SwitcherIconProps) =>
253254
renderSwitcherIcon(prefixCls.value, switcherIcon, showLine, nodeProps)
254255
}
255256
onCheck={handleCheck}
@@ -260,7 +261,7 @@ export default defineComponent({
260261
...slots,
261262
checkable: () => <span class={`${prefixCls.value}-checkbox-inner`} />,
262263
}}
263-
children={filterEmpty(slots.default?.())}
264+
children={children}
264265
></VcTree>
265266
);
266267
};

components/tree/utils/iconUtil.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import type { AntTreeNodeProps } from '../Tree';
77
import { isValidElement } from '../../_util/props-util';
88

99
import { cloneVNode } from 'vue';
10-
10+
export interface SwitcherIconProps extends AntTreeNodeProps {
11+
expanded: boolean;
12+
loading: boolean;
13+
}
1114
export default function renderSwitcherIcon(
1215
prefixCls: string,
1316
switcherIcon: any,
1417
showLine: boolean | { showLeafIcon: boolean } | undefined,
15-
props: AntTreeNodeProps,
18+
props: SwitcherIconProps,
1619
) {
1720
const { isLeaf, expanded, loading } = props;
1821
let icon = switcherIcon;

components/vc-tree/MotionTreeNode.tsx

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import TreeNode from './TreeNode';
22
import type { FlattenNode } from './interface';
3-
import type { TreeNodeRequiredProps } from './utils/treeUtil';
4-
import { getTreeNodeProps } from './utils/treeUtil';
53
import { useInjectTreeContext } from './contextTypes';
64
import type { PropType } from 'vue';
75
import {
@@ -28,7 +26,7 @@ export default defineComponent({
2826
onMotionStart: Function,
2927
onMotionEnd: Function,
3028
motionType: String,
31-
treeNodeRequiredProps: { type: Object as PropType<TreeNodeRequiredProps> },
29+
// treeNodeRequiredProps: { type: Object as PropType<TreeNodeRequiredProps> },
3230
},
3331
slots: ['title', 'icon', 'switcherIcon', 'checkable'],
3432
setup(props, { attrs, slots }) {
@@ -73,8 +71,7 @@ export default defineComponent({
7371
});
7472

7573
return () => {
76-
const { motion, motionNodes, motionType, active, treeNodeRequiredProps, ...otherProps } =
77-
props;
74+
const { motion, motionNodes, motionType, active, eventKey, ...otherProps } = props;
7875
if (motionNodes) {
7976
return (
8077
<Transition
@@ -94,17 +91,15 @@ export default defineComponent({
9491
} = treeNode;
9592
delete restProps.children;
9693

97-
const treeNodeProps = getTreeNodeProps(key, treeNodeRequiredProps);
98-
9994
return (
10095
<TreeNode
10196
v-slots={slots}
10297
{...restProps}
103-
{...treeNodeProps}
10498
title={title}
10599
active={active}
106100
data={treeNode.data}
107101
key={key}
102+
eventKey={key}
108103
isStart={isStart}
109104
isEnd={isEnd}
110105
/>
@@ -122,6 +117,7 @@ export default defineComponent({
122117
style={attrs.style}
123118
{...otherProps}
124119
active={active}
120+
eventKey={eventKey}
125121
/>
126122
);
127123
};

components/vc-tree/NodeList.tsx

+17-40
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44

55
import { computed, defineComponent, ref, shallowRef, watch } from 'vue';
66
import VirtualList from '../vc-virtual-list';
7+
import omit from '../_util/omit';
8+
import { useInjectKeysState, useInjectTreeContext } from './contextTypes';
79
import type { FlattenNode, DataEntity, DataNode, ScrollTo } from './interface';
810
import MotionTreeNode from './MotionTreeNode';
911
import type { NodeListProps } from './props';
1012
import { nodeListProps } from './props';
1113
import { findExpandedKeys, getExpandRange } from './utils/diffUtil';
12-
import { getTreeNodeProps, getKey } from './utils/treeUtil';
14+
import { getKey } from './utils/treeUtil';
1315

1416
const HIDDEN_STYLE = {
1517
width: 0,
@@ -97,26 +99,29 @@ export default defineComponent({
9799
// =============================== Ref ================================
98100
const listRef = ref();
99101
const indentMeasurerRef = ref();
102+
const { expandedKeys, flattenNodes } = useInjectKeysState();
100103
expose({
101104
scrollTo: scroll => {
102105
listRef.value.scrollTo(scroll);
103106
},
104107
getIndentWidth: () => indentMeasurerRef.value.offsetWidth,
105108
});
106109
// ============================== Motion ==============================
107-
const transitionData = shallowRef<FlattenNode[]>(props.data);
110+
const transitionData = shallowRef<FlattenNode[]>(flattenNodes.value);
108111
const transitionRange = shallowRef([]);
109112
const motionType = ref<'show' | 'hide' | null>(null);
110113

111114
function onMotionEnd() {
112-
transitionData.value = props.data;
115+
transitionData.value = flattenNodes.value;
113116
transitionRange.value = [];
114117
motionType.value = null;
115118

116119
props.onListChangeEnd();
117120
}
121+
122+
const context = useInjectTreeContext();
118123
watch(
119-
[() => [...props.expandedKeys], () => props.data],
124+
[() => expandedKeys.value.slice(), flattenNodes],
120125
([expandedKeys, data], [prevExpandedKeys, prevData]) => {
121126
const diffExpanded = findExpandedKeys(prevExpandedKeys, expandedKeys);
122127
if (diffExpanded.key !== null) {
@@ -160,7 +165,7 @@ export default defineComponent({
160165
);
161166
// We should clean up motion if is changed by dragging
162167
watch(
163-
() => props.dragging,
168+
() => context.value.dragging,
164169
dragging => {
165170
if (!dragging) {
166171
onMotionEnd();
@@ -169,27 +174,18 @@ export default defineComponent({
169174
);
170175

171176
const mergedData = computed(() =>
172-
props.motion === undefined ? transitionData.value : props.data,
177+
props.motion === undefined ? transitionData.value : flattenNodes.value,
173178
);
174-
179+
const onActiveChange = () => {
180+
props.onActiveChange(null);
181+
};
175182
return () => {
176183
const {
177184
prefixCls,
178-
data,
179185
selectable,
180186
checkable,
181-
expandedKeys,
182-
selectedKeys,
183-
checkedKeys,
184-
loadedKeys,
185-
loadingKeys,
186-
halfCheckedKeys,
187-
keyEntities,
188187
disabled,
189188

190-
dragging,
191-
dragOverNodeKey,
192-
dropPosition,
193189
motion,
194190

195191
height,
@@ -204,25 +200,12 @@ export default defineComponent({
204200
onKeydown,
205201
onFocus,
206202
onBlur,
207-
onActiveChange,
208203

209204
onListChangeStart,
210205
onListChangeEnd,
211206

212207
...domProps
213208
} = { ...props, ...attrs } as NodeListProps;
214-
215-
const treeNodeRequiredProps = {
216-
expandedKeys,
217-
selectedKeys,
218-
loadedKeys,
219-
loadingKeys,
220-
checkedKeys,
221-
halfCheckedKeys,
222-
dragOverNodeKey,
223-
dropPosition,
224-
keyEntities,
225-
};
226209
return (
227210
<>
228211
{focused && activeItem && (
@@ -262,7 +245,7 @@ export default defineComponent({
262245
</div>
263246

264247
<VirtualList
265-
{...domProps}
248+
{...omit(domProps, ['onActiveChange'])}
266249
data={mergedData.value}
267250
itemKey={itemKey as any}
268251
height={height}
@@ -293,15 +276,12 @@ export default defineComponent({
293276
const mergedKey = getKey(key, pos);
294277
delete restProps.key;
295278
delete restProps.children;
296-
297-
const treeNodeProps = getTreeNodeProps(mergedKey, treeNodeRequiredProps);
298279
return (
299280
<MotionTreeNode
300281
{...restProps}
301-
{...treeNodeProps}
282+
eventKey={mergedKey}
302283
title={title}
303284
active={!!activeItem && key === activeItem.key}
304-
pos={pos}
305285
data={treeNode.data}
306286
isStart={isStart}
307287
isEnd={isEnd}
@@ -310,10 +290,7 @@ export default defineComponent({
310290
motionType={motionType.value}
311291
onMotionStart={onListChangeStart}
312292
onMotionEnd={onMotionEnd}
313-
treeNodeRequiredProps={treeNodeRequiredProps}
314-
onMousemove={() => {
315-
onActiveChange(null);
316-
}}
293+
onMousemove={onActiveChange}
317294
/>
318295
);
319296
},

0 commit comments

Comments
 (0)