Browse Source

Merge branch 'main' into release

pointhalo 2 years ago
parent
commit
94ca27d341
2 changed files with 51 additions and 31 deletions
  1. 0 16
      packages/semi-ui/image/image.tsx
  2. 51 15
      packages/semi-ui/image/preview.tsx

+ 0 - 16
packages/semi-ui/image/image.tsx

@@ -82,22 +82,6 @@ export default class Image extends BaseComponent<ImageProps, ImageStates> {
         return willUpdateStates;
         return willUpdateStates;
     }
     }
 
 
-    componentDidMount() {
-        this.observeImage();
-    }
-
-    componentDidUpdate(prevProps: ImageProps, prevState: ImageStates) {
-        prevProps.src !== this.props.src && this.observeImage();
-    }
-
-    observeImage() {
-        if (!this.isLazyLoad()) {
-            return;
-        }
-        const { previewObserver } = this.context;
-        previewObserver.observe(this.imgRef.current);
-    }
-
     isInGroup() {
     isInGroup() {
         return Boolean(this.context && this.context.isGroup);
         return Boolean(this.context && this.context.isGroup);
     }
     }

+ 51 - 15
packages/semi-ui/image/preview.tsx

@@ -1,4 +1,4 @@
-import React, { ReactNode } from "react";
+import React, { ReactNode, isValidElement } from "react";
 import { PreviewContext } from "./previewContext";
 import { PreviewContext } from "./previewContext";
 import BaseComponent from "../_base/baseComponent";
 import BaseComponent from "../_base/baseComponent";
 import PropTypes, { array } from "prop-types";
 import PropTypes, { array } from "prop-types";
@@ -7,7 +7,7 @@ import PreviewInner from "./previewInner";
 import PreviewFoundation from "@douyinfe/semi-foundation/image/previewFoundation";
 import PreviewFoundation from "@douyinfe/semi-foundation/image/previewFoundation";
 import { getUuidShort } from "@douyinfe/semi-foundation/utils/uuid";
 import { getUuidShort } from "@douyinfe/semi-foundation/utils/uuid";
 import { cssClasses } from "@douyinfe/semi-foundation/image/constants";
 import { cssClasses } from "@douyinfe/semi-foundation/image/constants";
-import { isObject } from "lodash";
+import { isObject, isEqual } from "lodash";
 import "@douyinfe/semi-foundation/image/image.scss";
 import "@douyinfe/semi-foundation/image/image.scss";
 
 
 const prefixCls = cssClasses.PREFIX;
 const prefixCls = cssClasses.PREFIX;
@@ -81,21 +81,50 @@ export default class Preview extends BaseComponent<PreviewProps, PreviewState> {
         this.foundation = new PreviewFoundation(this.adapter);
         this.foundation = new PreviewFoundation(this.adapter);
         this.previewGroupId = getUuidShort({ prefix: "semi-image-preview-group", length: 4 });
         this.previewGroupId = getUuidShort({ prefix: "semi-image-preview-group", length: 4 });
         this.previewRef = React.createRef<PreviewInner>();
         this.previewRef = React.createRef<PreviewInner>();
-        this.previewObserver = new IntersectionObserver(entries => {
-            entries.forEach(item => {
-                const src = (item.target as any).dataset?.src;
-                if (item.isIntersecting && src) {
-                    (item.target as any).src = src;
-                    (item.target as any).removeAttribute("data-src");
+    }
+
+    componentDidMount() {
+        this.props.lazyLoad && this.observerImages();
+    }
+
+    componentDidUpdate(prevProps) {
+        if (this.props.lazyLoad) {
+            const prevChildrenKeys = React.Children.toArray(prevProps.children).map((child) =>
+                isValidElement(child) ? child.key : null
+            );
+            const currChildrenKeys = React.Children.toArray(this.props.children).map((child) =>
+                isValidElement(child) ? child.key : null
+            );
+        
+            if (!isEqual(prevChildrenKeys, currChildrenKeys)) {
+                this.observerImages();
+            }
+        }
+    }
+
+    observerImages = () => {
+        if (this.previewObserver) {
+            // cancel the observation of all elements of the previous observer
+            this.previewObserver.disconnect();
+        } else {
+            this.previewObserver = new IntersectionObserver(entries => {
+                entries.forEach(item => {
+                    const src = (item.target as any).dataset?.src;
+                    if (item.isIntersecting && src) {
+                        (item.target as any).src = src;
+                        (item.target as any).removeAttribute("data-src");
+                    }
                     this.previewObserver.unobserve(item.target);
                     this.previewObserver.unobserve(item.target);
-                }
-            });
-        },
-        {
-            root: document.querySelector(`#${this.previewGroupId}`),
-            rootMargin: props.lazyLoadMargin, 
+                });
+            },
+            {
+                root: document.querySelector(`#${this.previewGroupId}`),
+                rootMargin: this.props.lazyLoadMargin, 
+            }
+            );
         }
         }
-        );
+        const allImgElement = document.querySelectorAll(`.${prefixCls}-img`);
+        allImgElement.forEach(item => this.previewObserver.observe(item));
     }
     }
 
 
     static getDerivedStateFromProps(props: PreviewProps, state: PreviewState) {
     static getDerivedStateFromProps(props: PreviewProps, state: PreviewState) {
@@ -109,6 +138,13 @@ export default class Preview extends BaseComponent<PreviewProps, PreviewState> {
         return willUpdateStates;
         return willUpdateStates;
     }
     }
 
 
+    componentWillUnmount(): void {
+        if (this.previewObserver) {
+            this.previewObserver.disconnect();
+            this.previewObserver = null;
+        }
+    }
+
     handleVisibleChange = (newVisible: boolean) => {
     handleVisibleChange = (newVisible: boolean) => {
         this.foundation.handleVisibleChange(newVisible);
         this.foundation.handleVisibleChange(newVisible);
     };
     };