|
@@ -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);
|
|
|
};
|
|
};
|