Skip to content

Commit 38f3d86

Browse files
QuentinHsugithub-actions[bot]uyarntdesign-botWesley-0808
authored
fix(space): fix fragment virtual node has not been expanded (#5388)
* feat(hooks): add useFlatChildrenSlots hook for recursive slot flattening * fix(space): replace useChildSlots with useFlatChildrenSlots for improved slot handling * chore: update snapshot * fix(space): handle Teleport nodes in renderChildren to prevent rendering issues ref #5296 * fix(space): refactor child slot handling to improve clarity and functionality * fix(upload): remove unnecessary t-space-item divs from snapshots for cleaner output * fix(slot): refine documentation for useFlatChildrenSlots function * chore: stash changelog [ci skip] * chore: stash changelog [ci skip] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: wū yāng <[email protected]> Co-authored-by: tdesign-bot <[email protected]> Co-authored-by: Wesley <[email protected]>
1 parent c303a6b commit 38f3d86

File tree

3 files changed

+46
-16
lines changed

3 files changed

+46
-16
lines changed

packages/components/hooks/slot.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
VNodeArrayChildren,
1010
RendererElement,
1111
VNodeChild,
12+
isVNode,
1213
} from 'vue';
1314
import { isArray } from 'lodash-es';
1415
import { getChildren } from '../utils/render-tnode';
@@ -73,3 +74,25 @@ export function useChildSlots(): () => (
7374
.flat();
7475
};
7576
}
77+
78+
/**
79+
* 递归展开所有 Fragment,并跳过 Comment 节点,返回一维 VNodeChild 数组
80+
* @example const useFlatChildrenSlots = useFlatChildrenSlotsHook()
81+
* @example useFlatChildrenSlots(children)
82+
*/
83+
export function useFlatChildrenSlots() {
84+
function getFlatChildren(children: VNodeChild[]): VNodeChild[] {
85+
const result: VNodeChild[] = [];
86+
children.forEach((child) => {
87+
if (isVNode(child) && child.type === Fragment && Array.isArray(child.children)) {
88+
result.push(...getFlatChildren(child.children as VNodeChild[]));
89+
} else if (isVNode(child) && child.type === Comment) {
90+
// skip comment
91+
} else {
92+
result.push(child);
93+
}
94+
});
95+
return result;
96+
}
97+
return getFlatChildren;
98+
}

packages/components/space/space.tsx

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { defineComponent, computed, CSSProperties, Fragment, Comment, isVNode } from 'vue';
1+
import { defineComponent, computed, CSSProperties, Fragment, isVNode, Teleport } from 'vue';
22
import props from './props';
33
import { usePrefixClass } from '../hooks/useConfig';
44
import { useTNodeJSX } from '../hooks/tnode';
5-
import { useChildSlots } from '../hooks/slot';
5+
import { useChildSlots, useFlatChildrenSlots } from '../hooks/slot';
66
import { isNumber } from 'lodash-es';
77
import { isString } from 'lodash-es';
88
import { isArray } from 'lodash-es';
@@ -23,6 +23,7 @@ export default defineComponent({
2323
const COMPONENT_NAME = usePrefixClass('space');
2424
const renderTNodeJSX = useTNodeJSX();
2525
const getChildSlots = useChildSlots();
26+
const getFlatChildren = useFlatChildrenSlots();
2627

2728
const needPolyfill = computed(() => props.forceFlexGapPolyfill || defaultNeedPolyfill);
2829

@@ -52,22 +53,21 @@ export default defineComponent({
5253
}
5354
return style;
5455
});
55-
5656
function renderChildren() {
57-
const children = getChildSlots();
57+
const children = getFlatChildren(getChildSlots());
5858
const separatorContent = renderTNodeJSX('separator');
59-
return children
60-
.filter((child) => (isVNode(child) ? child.type !== Comment : true))
61-
.map((child, index) => {
62-
// filter last child
63-
const showSeparator = index + 1 !== children.length && separatorContent;
64-
return (
65-
<Fragment>
66-
<div class={`${COMPONENT_NAME.value}-item`}>{child}</div>
67-
{showSeparator && <div class={`${COMPONENT_NAME.value}-item-separator`}>{separatorContent}</div>}
68-
</Fragment>
69-
);
70-
});
59+
return children.map((child, index) => {
60+
const isTeleport = isVNode(child) && child.type === Teleport;
61+
if (isTeleport) return null;
62+
// filter last child
63+
const showSeparator = index + 1 !== children.length && separatorContent;
64+
return (
65+
<Fragment>
66+
<div class={`${COMPONENT_NAME.value}-item`}>{child}</div>
67+
{showSeparator && <div class={`${COMPONENT_NAME.value}-item-separator`}>{separatorContent}</div>}
68+
</Fragment>
69+
);
70+
});
7171
}
7272

7373
return () => {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
pr_number: 5388
3+
contributor: QuentinHsu
4+
---
5+
6+
- fix(Space): 修复`fragment`虚拟节点未展开的问题 @QuentinHsu ([#5388](https://github.com/Tencent/tdesign-vue-next/pull/5388))
7+
- fix(Space): 修复`teleport`结构意外渲染为`SpaceItem`节点,导致额外占用间距的问题 @QuentinHsu ([#5388](https://github.com/Tencent/tdesign-vue-next/pull/5388))

0 commit comments

Comments
 (0)