700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Ant-design 源码分析之数据展示(十)Image

Ant-design 源码分析之数据展示(十)Image

时间:2022-08-06 17:24:31

相关推荐

Ant-design 源码分析之数据展示(十)Image

Ant-design 源码分析之数据展示(十)Image

SC@SDUSC

一、组件结构

1、ant代码结构

2、组件结构

ant中Image的index.tsx中引入了PreviewGroup。

二、antd组件调用关系

1、index.tsx

导入相应模块以及相应的ICON图标

import * as React from 'react';import {useContext } from 'react';import EyeOutlined from '@ant-design/icons/EyeOutlined';import RcImage, {ImageProps } from 'rc-image';import defaultLocale from '../locale/en_US';import PreviewGroup, {icons } from './PreviewGroup';import {ConfigContext } from '../config-provider';import {getTransitionName } from '../_util/motion';

声明CompositionImage接口

export interface CompositionImage<P> extends React.FC<P> {PreviewGroup: typeof PreviewGroup;}

alt:图像描述,类型为string

fallback:加载失败容错地址,类型为string

height:图像高度,类型为string | number

placeholder:加载占位, 为 true 时使用默认占位,类型为ReactNode

preview:预览参数,为 false 时禁用,类型为boolean | previewType

src:图片地址,类型为string

width:图像宽度,类型为string | number

onError:加载错误回调,类型为(event: Event) => void

const Image: CompositionImage<ImageProps> = ({prefixCls: customizePrefixCls,preview,...otherProps}) => {const {getPrefixCls } = useContext(ConfigContext);const prefixCls = getPrefixCls('image', customizePrefixCls);const rootPrefixCls = getPrefixCls();const {locale: contextLocale = defaultLocale } = useContext(ConfigContext);const imageLocale = contextLocale.Image || defaultLocale.Image;const mergedPreview = React.useMemo(() => {if (preview === false) {return preview;}const _preview = typeof preview === 'object' ? preview : {};return {mask: (<div className={`${prefixCls}-mask-info`}><EyeOutlined />{imageLocale?.preview}</div>),icons,..._preview,transitionName: getTransitionName(rootPrefixCls, 'zoom', _preview.transitionName),maskTransitionName: getTransitionName(rootPrefixCls, 'fade', _preview.maskTransitionName),};}, [preview, imageLocale]);return <RcImage prefixCls={prefixCls} preview={mergedPreview} {...otherProps} />;};

export {ImageProps };Image.PreviewGroup = PreviewGroup;export default Image;

2、PreviewGroup.tsx

导入相应模块以及相应的ICON图标

import * as React from 'react';import RcImage from 'rc-image';import RotateLeftOutlined from '@ant-design/icons/RotateLeftOutlined';import RotateRightOutlined from '@ant-design/icons/RotateRightOutlined';import ZoomInOutlined from '@ant-design/icons/ZoomInOutlined';import ZoomOutOutlined from '@ant-design/icons/ZoomOutOutlined';import CloseOutlined from '@ant-design/icons/CloseOutlined';import LeftOutlined from '@ant-design/icons/LeftOutlined';import RightOutlined from '@ant-design/icons/RightOutlined';import {GroupConsumerProps } from 'rc-image/lib/PreviewGroup';import {ConfigContext } from '../config-provider';import {getTransitionName } from '../_util/motion';

声明接口

export const icons = {rotateLeft: <RotateLeftOutlined />,rotateRight: <RotateRightOutlined />,zoomIn: <ZoomInOutlined />,zoomOut: <ZoomOutOutlined />,close: <CloseOutlined />,left: <LeftOutlined />,right: <RightOutlined />,};

const InternalPreviewGroup: React.FC<GroupConsumerProps> = ({previewPrefixCls: customizePrefixCls,preview,...props}) => {const {getPrefixCls } = React.useContext(ConfigContext);const prefixCls = getPrefixCls('image-preview', customizePrefixCls);const rootPrefixCls = getPrefixCls();//预览参数为false时禁用const mergedPreview = React.useMemo(() => {if (preview === false) {return preview;}const _preview = typeof preview === 'object' ? preview : {};return {..._preview,transitionName: getTransitionName(rootPrefixCls, 'zoom', _preview.transitionName),maskTransitionName: getTransitionName(rootPrefixCls, 'fade', _preview.maskTransitionName),};}, [preview]);return (<RcImage.PreviewGrouppreview={mergedPreview}previewPrefixCls={prefixCls}icons={icons}{...props}/>);};export default InternalPreviewGroup;

3、Rc-Image:Image.tsx

导入相应模块以及相应的ICON图标

import * as React from 'react';import {useState } from 'react';import cn from 'classnames';import {getOffset } from 'rc-util/lib/Dom/css';import useMergedState from 'rc-util/lib/hooks/useMergedState';import {GetContainer } from 'rc-util/lib/PortalWrapper';import Preview, {PreviewProps } from './Preview';import PreviewGroup, {context } from './PreviewGroup';import {IDialogPropTypes } from 'rc-dialog/lib/IDialogPropTypes';

声明ImagePreviewType接口

export interface ImagePreviewTypeextends Omit<IDialogPropTypes,'mask' | 'visible' | 'closable' | 'prefixCls' | 'onClose' | 'afterClose' | 'wrapClassName'> {src?: string;visible?: boolean;onVisibleChange?: (value: boolean, prevValue: boolean) => void;getContainer?: GetContainer | false;mask?: React.ReactNode;maskClassName?: string;icons?: PreviewProps['icons'];}

visible?: boolean;

onVisibleChange?: (visible, prevVisible) => void;

getContainer?:string | HTMLElement | (() => HTMLElement)

src:图片地址,类型为string

mask:,类型为ReactNode

maskClassName:string

current:number

let uuid = 0;export interface ImagePropsextends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'placeholder' | 'onClick'> {// Originalsrc?: string;wrapperClassName?: string;wrapperStyle?: React.CSSProperties;prefixCls?: string;previewPrefixCls?: string;placeholder?: React.ReactNode;fallback?: string;preview?: boolean | ImagePreviewType;/*** @deprecated since version 3.2.1*/onPreviewClose?: (value: boolean, prevValue: boolean) => void;onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;onError?: (e: React.SyntheticEvent<HTMLImageElement, Event>) => void;}interface CompoundedComponent<P> extends React.FC<P> {PreviewGroup: typeof PreviewGroup;}

图片状态

type ImageStatus = 'normal' | 'error' | 'loading';const ImageInternal: CompoundedComponent<ImageProps> = ({src: imgSrc,alt,onPreviewClose: onInitialPreviewClose,prefixCls = 'rc-image',previewPrefixCls = `${prefixCls}-preview`,placeholder,fallback,width,height,style,preview = true,className,onClick,onError: onImageError,wrapperClassName,wrapperStyle,// ImgcrossOrigin,decoding,loading,referrerPolicy,sizes,srcSet,useMap,...otherProps}) => {//加载占位为true是默认占位const isCustomPlaceholder = placeholder && placeholder !== true;const {src: previewSrc,visible: previewVisible = undefined,onVisibleChange: onPreviewVisibleChange = onInitialPreviewClose,getContainer: getPreviewContainer = undefined,mask: previewMask,maskClassName,icons,...dialogProps}: ImagePreviewType = typeof preview === 'object' ? preview : {};const src = previewSrc ?? imgSrc;const isControlled = previewVisible !== undefined;const [isShowPreview, setShowPreview] = useMergedState(!!previewVisible, {value: previewVisible,onChange: onPreviewVisibleChange,});const [status, setStatus] = useState<ImageStatus>(isCustomPlaceholder ? 'loading' : 'normal');//图片状态const [mousePosition, setMousePosition] = useState<null | {x: number; y: number }>(null);const isError = status === 'error';const {isPreviewGroup,setCurrent,setShowPreview: setGroupShowPreview,setMousePosition: setGroupMousePosition,registerImage,} = React.useContext(context);const [currentId] = React.useState<number>(() => {uuid += 1;return uuid;});const canPreview = preview && !isError;const isLoaded = React.useRef(false);

const onLoad = () => {setStatus('normal');};const onError = (e: React.SyntheticEvent<HTMLImageElement, Event>) => {if (onImageError) {onImageError(e);}setStatus('error');};

const onPreview: React.MouseEventHandler<HTMLDivElement> = e => {if (!isControlled) {const {left, top } = getOffset(e.target);if (isPreviewGroup) {setCurrent(currentId);setGroupMousePosition({x: left,y: top,});} else {setMousePosition({x: left,y: top,});}}if (isPreviewGroup) {setGroupShowPreview(true);} else {setShowPreview(true);}if (onClick) onClick(e);};

const onPreviewClose = (e: React.SyntheticEvent<Element>) => {e.stopPropagation();setShowPreview(false);if (!isControlled) {setMousePosition(null);}};const getImgRef = (img?: HTMLImageElement) => {isLoaded.current = false;if (status !== 'loading') return;if (img?.complete && (img.naturalWidth || img.naturalHeight)) {isLoaded.current = true;onLoad();}};

// Keep order start// Resolve /ant-design/ant-design/issues/28881// Only need unRegister when component unMountReact.useEffect(() => {const unRegister = registerImage(currentId, src);return unRegister;}, []);React.useEffect(() => {registerImage(currentId, src, canPreview);}, [src, canPreview]);// Keep order endReact.useEffect(() => {if (isError) {setStatus('normal');}if (isCustomPlaceholder && !isLoaded.current) {setStatus('loading');}}, [imgSrc]);const wrapperClass = cn(prefixCls, wrapperClassName, {[`${prefixCls}-error`]: isError,});//fallbackconst mergedSrc = isError && fallback ? fallback : src;const imgCommonProps = {crossOrigin,decoding,loading,referrerPolicy,sizes,srcSet,useMap,alt,className: cn(`${prefixCls}-img`,{[`${prefixCls}-img-placeholder`]: placeholder === true,},className,),style: {height,...style,},};return (<><div{...otherProps}className={wrapperClass}onClick={canPreview ? onPreview : onClick}style={{width,height,...wrapperStyle,}}><img{...imgCommonProps}ref={getImgRef}{...(isError && fallback? {src: fallback,}: {onLoad, onError, src: imgSrc })}/>{status === 'loading' && (<div aria-hidden="true" className={`${prefixCls}-placeholder`}>{placeholder}</div>)}{/* Preview Click Mask */}{previewMask && canPreview && (<div className={cn(`${prefixCls}-mask`, maskClassName)}>{previewMask}</div>)}</div>{!isPreviewGroup && canPreview && (<Previewaria-hidden={!isShowPreview}visible={isShowPreview}prefixCls={previewPrefixCls}onClose={onPreviewClose}mousePosition={mousePosition}src={mergedSrc}alt={alt}getContainer={getPreviewContainer}icons={icons}{...dialogProps}/>)}</>);};ImageInternal.PreviewGroup = PreviewGroup;ImageInternal.displayName = 'Image';export default ImageInternal;

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。