liumingyi_1 преди 5 години
родител
ревизия
5bc6556907
променени са 5 файла, в които са добавени 63 реда и са изтрити 89 реда
  1. 44 81
      src/PhotoConsumer.tsx
  2. 2 0
      src/PhotoSlider.tsx
  3. 9 6
      src/components/SlideWrap.tsx
  4. 7 1
      src/photo-context.ts
  5. 1 1
      src/variables.ts

+ 44 - 81
src/PhotoConsumer.tsx

@@ -1,65 +1,53 @@
 import React from 'react';
 import uniqueId from 'lodash.uniqueid';
 import isMobile from './utils/isMobile';
-import PhotoContext, {
-  onShowType,
-  addItemType,
-  removeItemType,
-} from './photo-context';
+import PhotoContext, { PhotoContextType } from './photo-context';
 
-export interface IPhotoViewItem {
+export interface IPhotoConsumer {
   src: string;
   intro?: React.ReactNode;
   children?: React.ReactElement<any>;
-  onShow: onShowType;
-  addItem: addItemType;
-  removeItem: removeItemType;
 }
 
-type PhotoViewState = {
-  clientX: number | undefined;
-  clientY: number | undefined;
-};
-
-class PhotoViewItem extends React.Component<IPhotoViewItem, PhotoViewState> {
-  readonly state = {
+const PhotoConsumer: React.FC<IPhotoConsumer> = ({ src, intro, children }) => {
+  const photoContext = React.useContext<PhotoContextType>(PhotoContext);
+  const key = React.useMemo<string>(() => uniqueId(), [] as readonly []);
+  const [position, updatePosition] = React.useState<{
+    clientX: number | undefined;
+    clientY: number | undefined;
+  }>({
     clientX: undefined,
     clientY: undefined,
-  };
+  });
 
-  private key: string = uniqueId();
+  React.useEffect(
+    () => {
+      photoContext.addItem(key, src, intro);
+      return () => {
+        photoContext.removeItem(key);
+      };
+    },
+    [] as readonly [],
+  );
 
-  componentDidMount() {
-    const { addItem, src, intro } = this.props;
-    addItem(this.key, src, intro);
-  }
-
-  componentWillUnmount() {
-    const { removeItem } = this.props;
-    removeItem(this.key);
-  }
-
-  handleTouchStart = e => {
+  function handleTouchStart(e) {
     const { clientX, clientY } = e.touches[0];
-    this.setState({
+    updatePosition({
       clientX,
       clientY,
     });
-    const { children } = this.props;
     if (children) {
       const { onTouchStart } = children.props;
       if (onTouchStart) {
         onTouchStart(e);
       }
     }
-  };
+  }
 
-  handleTouchEnd = e => {
-    const { onShow, children } = this.props;
-    const { clientX: newClientX, clientY: newClientY } = e.changedTouches[0];
-    const { clientX, clientY } = this.state;
-    if (clientX === newClientX && clientY === newClientY) {
-      onShow(this.key);
+  function handleTouchEnd(e) {
+    const { clientX, clientY } = e.changedTouches[0];
+    if (position.clientX === clientX && position.clientY === clientY) {
+      photoContext.onShow(key);
     }
     if (children) {
       const { onTouchEnd } = children.props;
@@ -67,57 +55,32 @@ class PhotoViewItem extends React.Component<IPhotoViewItem, PhotoViewState> {
         onTouchEnd(e);
       }
     }
-  };
+  }
 
-  handleClick = e => {
-    const { onShow, children } = this.props;
-    onShow(this.key);
+  function handleClick(e) {
+    photoContext.onShow(key);
     if (children) {
       const { onClick } = children.props;
       if (onClick) {
         onClick(e);
       }
     }
-  };
-
-  render() {
-    const { children } = this.props;
-    if (children) {
-      return React.Children.only(
-        React.cloneElement(
-          children,
-          isMobile
-            ? {
-                onTouchStart: this.handleTouchStart,
-                onTouchEnd: this.handleTouchEnd,
-              }
-            : { onClick: this.handleClick },
-        ),
-      );
-    }
-    return null;
   }
-}
-
-export interface IPhotoConsumer {
-  src: string;
-  intro?: React.ReactNode;
-  children?: React.ReactElement<any>;
-}
 
-const PhotoConsumer: React.SFC<IPhotoConsumer> = ({
-  src,
-  intro,
-  children,
-  ...restProps
-}) => (
-  <PhotoContext.Consumer>
-    {value => (
-      <PhotoViewItem {...value} {...restProps} src={src} intro={intro}>
-        {children}
-      </PhotoViewItem>
-    )}
-  </PhotoContext.Consumer>
-);
+  if (children) {
+    return React.Children.only(
+      React.cloneElement(
+        children,
+        isMobile
+          ? {
+              onTouchStart: handleTouchStart,
+              onTouchEnd: handleTouchEnd,
+            }
+          : { onClick: handleClick },
+      ),
+    );
+  }
+  return null;
+};
 
 export default PhotoConsumer;

+ 2 - 0
src/PhotoSlider.tsx

@@ -83,6 +83,8 @@ export default class PhotoSlider extends React.Component<
       canPullClose: true,
     };
     this.handleResize = debounce(this.handleResize, 32);
+    // 避免事件穿透
+    this.handlePhotoMaskTap = debounce(this.handlePhotoMaskTap, 200);
   }
 
   componentDidMount() {

+ 9 - 6
src/components/SlideWrap.tsx

@@ -7,12 +7,15 @@ const SlideWrap: React.FC<{ className?: string }> = ({
   className,
   children,
 }) => {
-  const [dialogNode] = React.useState(() => {
-    // 创建容器
-    const dialogNode = document.createElement('section');
-    document.body.appendChild(dialogNode);
-    return dialogNode;
-  });
+  const dialogNode = React.useMemo(
+    () => {
+      // 容器
+      const dialogNode = document.createElement('section');
+      document.body.appendChild(dialogNode);
+      return dialogNode;
+    },
+    [] as readonly [],
+  );
   const originalOverflowCallback = React.useRef('');
 
   React.useEffect(

+ 7 - 1
src/photo-context.ts

@@ -10,7 +10,13 @@ export type addItemType = (
 
 export type removeItemType = (key?: string) => void;
 
-export default React.createContext({
+export interface PhotoContextType {
+  onShow: onShowType,
+  addItem: addItemType,
+  removeItem: removeItemType,
+}
+
+export default React.createContext<PhotoContextType>({
   onShow() {},
   addItem() {},
   removeItem() {},

+ 1 - 1
src/variables.ts

@@ -36,7 +36,7 @@ export const maxScale: number = 6;
 /**
  * 滑动加速度
  */
-export const slideAcceleration: number = 0.01;
+export const slideAcceleration: number = 0.005;
 
 /**
  * 缩放弹性缓冲