From b0ef3393438f9e8219bc2f81a77003196a0684ac Mon Sep 17 00:00:00 2001 From: changlin2569 <1119785353@qq.com> Date: Fri, 1 Mar 2024 14:54:45 +0800 Subject: [PATCH 1/2] feat: add lazyRender prop for Collapsible --- content/show/collapsible/index-en-US.md | 1 + content/show/collapsible/index.md | 1 + .../semi-ui/collapsible/_story/collapsible.stories.jsx | 4 +++- packages/semi-ui/collapsible/index.tsx | 10 +++++++--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/content/show/collapsible/index-en-US.md b/content/show/collapsible/index-en-US.md index febc492be8..0410d54f9a 100644 --- a/content/show/collapsible/index-en-US.md +++ b/content/show/collapsible/index-en-US.md @@ -184,6 +184,7 @@ import { Collapsible, Button } from '@douyinfe/semi-ui'; | duration | Time of animation execution | number | 250 | - | | isOpen | Toggle whether to expand the content area | boolean | `false` | - | | keepDOM | Whether to keep the hidden panel in DOM tree, destroyed by default | boolean | `false` | 0.25.0 | +| lazyRender | Used with keepDOM, when true, the component will not be rendered when mounting | boolean | `true` | 2.24 | | motion | Toggle whether to turn on animation | Motion | `true` | - | | onMotionEnd | Animation end callback | () => void | - | - | | reCalcKey | When reCalcKey changes, the height of children will be reset. Used for optimize dynamic content rendering. | number \| string | - | 1.5.0 | diff --git a/content/show/collapsible/index.md b/content/show/collapsible/index.md index b9a6b961bb..dbf5b34216 100644 --- a/content/show/collapsible/index.md +++ b/content/show/collapsible/index.md @@ -216,6 +216,7 @@ import { Collapsible, Button } from '@douyinfe/semi-ui'; | fade | 是否开启淡入淡出 | boolean | false | 2.21.0 | | isOpen | 是否展开内容区域 | boolean | `false` | - | | keepDOM | 是否保留隐藏的面板 DOM 树,默认销毁 | boolean | `false` | 0.25.0 | +| lazyRender | 配合 keepDOM 使用,为 true 时挂载时不会渲染组件 | boolean | `true` | 2.24 | | motion | 是否开启动画 | boolean | `true` | - | | onMotionEnd | 动画结束的回调 | () => void | - | - | | reCalcKey | 当 reCalcKey 改变时,将重新计算子节点的高度,用于优化动态渲染时的计算 | number \| string | - | 1.5.0 | diff --git a/packages/semi-ui/collapsible/_story/collapsible.stories.jsx b/packages/semi-ui/collapsible/_story/collapsible.stories.jsx index 88e7573cb2..3722576515 100644 --- a/packages/semi-ui/collapsible/_story/collapsible.stories.jsx +++ b/packages/semi-ui/collapsible/_story/collapsible.stories.jsx @@ -81,7 +81,7 @@ class DemoDOM extends React.Component { return (
- + {collapsed}
@@ -91,6 +91,8 @@ class DemoDOM extends React.Component { export const KeepDom = () => ; +export const LazyRender = () => ; + class DefaultOpen extends React.Component { state = { isOpen: true, diff --git a/packages/semi-ui/collapsible/index.tsx b/packages/semi-ui/collapsible/index.tsx index 9a01cb1800..812b8421c4 100644 --- a/packages/semi-ui/collapsible/index.tsx +++ b/packages/semi-ui/collapsible/index.tsx @@ -19,6 +19,7 @@ export interface CollapsibleProps extends CollapsibleFoundationProps { isOpen?: boolean; duration?: number; keepDOM?: boolean; + lazyRender?: boolean; className?: string; style?: React.CSSProperties; collapseHeight?: number; @@ -42,6 +43,7 @@ class Collapsible extends BaseComponent { duration: 250, motion: true, keepDOM: false, + lazyRender: true, collapseHeight: 0, fade: false }) @@ -157,9 +159,8 @@ class Collapsible extends BaseComponent { isChildrenInRenderTree = () => { if (this.domRef.current) { return this.domRef.current.offsetHeight > 0; - } else { - return false; } + return false; } render() { @@ -173,6 +174,9 @@ class Collapsible extends BaseComponent { const wrapperCls = cls(`${cssClasses.PREFIX}-wrapper`, { [`${cssClasses.PREFIX}-transition`]: this.props.motion && this.state.isTransitioning }, this.props.className); + + const shouldRender = (this.props.keepDOM && !this.props.lazyRender) || this.props.collapseHeight !== 0 || this.state.visible || this.props.isOpen; + return (
{ id={this.props.id} > { - (this.props.keepDOM || this.props.collapseHeight !== 0 || this.state.visible || this.props.isOpen) && this.props.children + shouldRender && this.props.children }
From 4a46f80edf27c04b72721867bd9d9b62d851d110 Mon Sep 17 00:00:00 2001 From: changlin2569 <1119785353@qq.com> Date: Mon, 4 Mar 2024 14:42:13 +0800 Subject: [PATCH 2/2] test: add collapsible related test --- .../collapsible/__test__/collapsible.test.js | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 packages/semi-ui/collapsible/__test__/collapsible.test.js diff --git a/packages/semi-ui/collapsible/__test__/collapsible.test.js b/packages/semi-ui/collapsible/__test__/collapsible.test.js new file mode 100644 index 0000000000..c4b042b03f --- /dev/null +++ b/packages/semi-ui/collapsible/__test__/collapsible.test.js @@ -0,0 +1,44 @@ +import { clear } from 'jest-date-mock'; +import { Collapsible } from '../../index'; + +function getCollapsible(props, children) { + return ( + {children ? children :
hello
} +
); +} + +describe('collapsible', () => { + beforeEach(() => { + // Avoid `attachTo: document.body` Warning + const div = document.createElement('div'); + div.setAttribute('id', 'container'); + document.body.appendChild(div); + clear(); + }); + + it('keepDOM = true', async () => { + let component = getCollapsible({ keepDOM: true, motion: false }); + let collapsible = mount(component, { attachTo: document.getElementById('container') }) + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(false); + // set true + collapsible.setProps({ isOpen: true }); + collapsible.update(); // 必须调用一次update + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true); + collapsible.setProps({ isOpen: false }); + collapsible.update(); // 必须调用一次update + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(false); + }); + + it('keepDOM + lazyRender = false', () => { + let component = getCollapsible({ keepDOM: true, lazyRender: false }); + let collapsible = mount(component); + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true); + // set true + collapsible.setProps({ isOpen: true }); + collapsible.update(); // 必须调用一次update + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true); + collapsible.setProps({ isOpen: false }); + collapsible.update(); // 必须调用一次update + expect(collapsible.exists(`.collapsible-test-content`)).toEqual(true); + }); +}); \ No newline at end of file