2021SC@SDUSC
源码分析如下
首先导入了相关使用的模块
import * as React from 'react';
import RcDrawer from 'rc-drawer';
import CloseOutlined from '@ant-design/icons/CloseOutlined';
import classNames from 'classnames';
import { ConfigContext, DirectionType } from '../config-provider';
import { tuple } from '../_util/type';
import useForceUpdate from '../_util/hooks/useForceUpdate';
先定义了一个接口,有push和pull方法
type DrawerRef = {
push(): void;
pull(): void;
};
定义了一个抽屉的上下文来用于返回两个对象,一个消费者(使用数据),一个生产者(提供数据)类型为DrawerRef或空(null)
const DrawerContext = React.createContext<DrawerRef | null>(null);
函数:获取包含的内容
type getContainerFunc = () => HTMLElement;
组件所处的抽屉级别以及多级抽屉情况下所在位置
type ILevelMove = number | [number, number];
抽屉所处的四个位置
onst PlacementTypes = tuple('top', 'right', 'bottom', 'left');
type placementType = typeof PlacementTypes[number];
抽屉大小的两种(默认,可调)
const SizeTypes = tuple('default', 'large');
type sizeType = typeof SizeTypes[number];
添加属性:抽屉拉出来的距离
export interface PushState {
distance: string | number;
}
抽屉接口
autoFocus:抽屉展开后是否将焦点切换至其 Dom 节点
closable:能否关闭
closeIcon:关闭图标
destroyOnClose:关闭时销毁 Drawer 里的子元素
forceRender:是否预渲染抽屉内元素
getContainer:获取抽屉内元素
maskClosable:能否关闭遮罩
mask:是否显示遮罩
maskStyle:遮罩样式
style:样式
size:抽屉大小
drawerStyle:抽屉样式
headerStyle:头部样式
bodyStyle:body部分样式
title:标题
visible:是否显示
extra:抽屉右上角的额外操作
level:抽屉所处级别
export interface DrawerProps {
autoFocus?: boolean;
closable?: boolean;
closeIcon?: React.ReactNode;
destroyOnClose?: boolean;
forceRender?: boolean;
getContainer?: string | HTMLElement | getContainerFunc | false;
maskClosable?: boolean;
mask?: boolean;
maskStyle?: React.CSSProperties;
style?: React.CSSProperties;
size?: sizeType;
/** Wrapper dom node style of header and body */
drawerStyle?: React.CSSProperties;
headerStyle?: React.CSSProperties;
bodyStyle?: React.CSSProperties;
contentWrapperStyle?: React.CSSProperties;
title?: React.ReactNode;
visible?: boolean;
width?: number | string;
height?: number | string;
zIndex?: number;
prefixCls?: string;
push?: boolean | PushState;
placement?: placementType;
onClose?: (e: EventType) => void;
afterVisibleChange?: (visible: boolean) => void;
className?: string;
handler?: React.ReactNode;
keyboard?: boolean;
extra?: React.ReactNode;
footer?: React.ReactNode;
footerStyle?: React.CSSProperties;
level?: string | string[] | null | undefined;
levelMove?:
| ILevelMove
| ((e: { target: HTMLElement; open: boolean }) => ILevelMove);
}
默认抽出距离为180
const defaultPushState: PushState = { distance: 180 };
强制重新渲染
const forceUpdate = useForceUpdate();
父抽屉
const parentDrawer = React.useContext(DrawerContext);
关闭清除抽屉元素
const destroyClose = React.useRef<boolean>(false);
设定推拉函数(关闭打开)
const operations = React.useMemo(
() => ({
push() {
if (push) {
setPush(true);
}
},
pull() {
if (push) {
setPush(false);
}
},
}),
[push],
);
函数:如果本抽屉可见或父抽屉存在时,关闭该抽屉并将父抽屉拉出
React.useEffect(() => {
// fix: delete drawer in child and re-render, no push started.
// <Drawer>{show && <Drawer />}</Drawer>
if (visible && parentDrawer) {
parentDrawer.push();
}
return () => {
if (parentDrawer) {
parentDrawer.pull();
// parentDrawer = null;
}
};
}, []);
获取样式
const getOffsetStyle = () => {
// https://github.com/ant-design/ant-design/issues/24287
if (!visible && !mask) {
return {};
}
const offsetStyle: any = {};
if (placement === 'left' || placement === 'right') {
const defaultWidth = size === 'large' ? 736 : 378;
offsetStyle.width = typeof width === 'undefined' ? defaultWidth : width;
} else {
const defaultHeight = size === 'large' ? 736 : 378;
offsetStyle.height = typeof height === 'undefined' ? defaultHeight : height;
}
return offsetStyle;
};