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