Skip to content

Commit

Permalink
fix: Check passive support cause memo leak
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Jan 19, 2020
1 parent 02f8f8d commit e52ef83
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 56 deletions.
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"endOfLine": "lf",
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}
161 changes: 105 additions & 56 deletions src/DrawerChild.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ interface IState {
class DrawerChild extends React.Component<IDrawerChildProps, IState> {
static defaultProps = {
switchScrollingEffect: () => {},
}
};

public static getDerivedStateFromProps(props: IDrawerChildProps,
{ prevProps, _self }: { prevProps: IDrawerChildProps, _self: DrawerChild }) {
public static getDerivedStateFromProps(
props: IDrawerChildProps,
{ prevProps, _self }: { prevProps: IDrawerChildProps; _self: DrawerChild },
) {
const nextState = {
prevProps: props,
};
Expand Down Expand Up @@ -69,8 +71,8 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
private passive: { passive: boolean } | boolean;

private startPos: {
x: number,
y: number,
x: number;
y: number;
};

constructor(props: IDrawerChildProps) {
Expand All @@ -83,24 +85,26 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
public componentDidMount() {
if (!windowIsUndefined) {
let passiveSupported = false;
window.addEventListener(
'test',
() => { },
Object.defineProperty({}, 'passive', {
get: () => {
passiveSupported = true;
return null;
},
}),
);
try {
window.addEventListener(
'test',
null,
Object.defineProperty({}, 'passive', {
get: () => {
passiveSupported = true;
return null;
},
}),
);
} catch (err) {}
this.passive = passiveSupported ? { passive: false } : false;
}
const { open } = this.props;
this.drawerId = `drawer_id_${
Number(
(Date.now() + Math.random()).toString().replace('.', Math.round(Math.random() * 9).toString()),
).toString(16)
}`;
this.drawerId = `drawer_id_${Number(
(Date.now() + Math.random())
.toString()
.replace('.', Math.round(Math.random() * 9).toString()),
).toString(16)}`;
this.getLevelDom(this.props);
if (open) {
currentDrawer[this.drawerId] = open;
Expand All @@ -125,7 +129,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {

public componentWillUnmount() {
const { getOpenCount, open, switchScrollingEffect } = this.props;
const openCount = typeof getOpenCount === 'function' && getOpenCount()
const openCount = typeof getOpenCount === 'function' && getOpenCount();
delete currentDrawer[this.drawerId];
if (open) {
this.setLevelTransform(false);
Expand All @@ -141,7 +145,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
if (this.dom) {
this.dom.focus();
}
}
};

private removeStartHandler = (e: React.TouchEvent | TouchEvent) => {
if (e.touches.length > 1) {
Expand All @@ -151,7 +155,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
x: e.touches[0].clientX,
y: e.touches[0].clientY,
};
}
};

private removeMoveHandler = (e: React.TouchEvent | TouchEvent) => {
if (e.changedTouches.length > 1) {
Expand All @@ -164,17 +168,22 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
currentTarget === this.maskDom ||
currentTarget === this.handlerDom ||
(currentTarget === this.contentDom &&
getTouchParentScroll(currentTarget, e.target as HTMLElement, differX, differY))
getTouchParentScroll(
currentTarget,
e.target as HTMLElement,
differX,
differY,
))
) {
e.preventDefault();
}
}
};

private transitionEnd = (e: TransitionEvent) => {
const dom: HTMLElement = e.target as HTMLElement;
removeEventListener(dom, transitionEnd, this.transitionEnd);
dom.style.transition = '';
}
};

private onKeyDown = (e: React.KeyboardEvent) => {
if (e.keyCode === KeyCode.ESC) {
Expand All @@ -184,11 +193,14 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
onClose(e as any);
}
}
}
};

private onWrapperTransitionEnd = (e: React.TransitionEvent) => {
const { open, afterVisibleChange } = this.props;
if (e.target === this.contentWrapper && e.propertyName.match(/transform$/)) {
if (
e.target === this.contentWrapper &&
e.propertyName.match(/transform$/)
) {
this.dom.style.transition = '';
if (!open && this.getCurrentDrawerSome()) {
document.body.style.overflowX = '';
Expand All @@ -201,17 +213,22 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
afterVisibleChange(!!open);
}
}
}
};

private openLevelTransition = () => {
const { open, width, height } = this.props;
const { isHorizontal, placementName } = this.getHorizontalBoolAndPlacementName();
const {
isHorizontal,
placementName,
} = this.getHorizontalBoolAndPlacementName();
const contentValue = this.contentDom
? this.contentDom.getBoundingClientRect()[isHorizontal ? 'width' : 'height']
? this.contentDom.getBoundingClientRect()[
isHorizontal ? 'width' : 'height'
]
: 0;
const value = (isHorizontal ? width : height) || contentValue;
this.setLevelAndScrolling(open, placementName, value);
}
};

private setLevelTransform = (
open?: boolean,
Expand All @@ -229,13 +246,19 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
const $levelMove = transformArguments(levelMove, { target: dom, open });
levelValue = open ? $levelMove[0] : $levelMove[1] || 0;
}
const $value = typeof levelValue === 'number' ? `${levelValue}px` : levelValue;
let placementPos = placement === 'left' || placement === 'top' ? $value : `-${$value}`;
placementPos = showMask && placement === 'right' && right ?
`calc(${placementPos} + ${right}px)` : placementPos;
dom.style.transform = levelValue ? `${placementName}(${placementPos})` : '';
const $value =
typeof levelValue === 'number' ? `${levelValue}px` : levelValue;
let placementPos =
placement === 'left' || placement === 'top' ? $value : `-${$value}`;
placementPos =
showMask && placement === 'right' && right
? `calc(${placementPos} + ${right}px)`
: placementPos;
dom.style.transform = levelValue
? `${placementName}(${placementPos})`
: '';
});
}
};

private setLevelAndScrolling = (
open?: boolean,
Expand All @@ -244,16 +267,19 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
) => {
const { onChange } = this.props;
if (!windowIsUndefined) {
const right = document.body.scrollHeight >
(window.innerHeight || document.documentElement.clientHeight) &&
window.innerWidth > document.body.offsetWidth ? getScrollBarSize(true) : 0;
const right =
document.body.scrollHeight >
(window.innerHeight || document.documentElement.clientHeight) &&
window.innerWidth > document.body.offsetWidth
? getScrollBarSize(true)
: 0;
this.setLevelTransform(open, placementName, value, right);
this.toggleScrollingToDrawerAndBody(right);
}
if (onChange) {
onChange(open);
}
}
};

private toggleScrollingToDrawerAndBody = (right: number) => {
const { getOpenCount, getContainer, showMask, open } = this.props;
Expand All @@ -262,7 +288,12 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
// 处理 body 滚动
if (container && container.parentNode === document.body && showMask) {
const eventArray = ['touchstart'];
const domArray = [document.body, this.maskDom, this.handlerDom, this.contentDom];
const domArray = [
document.body,
this.maskDom,
this.handlerDom,
this.contentDom,
];
if (open && document.body.style.overflow !== 'hidden') {
if (right) {
this.addScrollingEffect(right);
Expand Down Expand Up @@ -306,10 +337,16 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
});
}
}
}
};

private addScrollingEffect = (right: number) => {
const { placement, duration, ease, getOpenCount, switchScrollingEffect } = this.props;
const {
placement,
duration,
ease,
getOpenCount,
switchScrollingEffect,
} = this.props;
const openCount = getOpenCount && getOpenCount();
if (openCount === 1) {
switchScrollingEffect();
Expand Down Expand Up @@ -337,10 +374,16 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
this.dom.style.transform = '';
}
});
}
};

private remScrollingEffect = (right: number) => {
const { placement, duration, ease, getOpenCount, switchScrollingEffect } = this.props;
const {
placement,
duration,
ease,
getOpenCount,
switchScrollingEffect,
} = this.props;
const openCount = getOpenCount && getOpenCount();
if (!openCount) {
switchScrollingEffect(true);
Expand Down Expand Up @@ -384,25 +427,28 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
if (this.dom) {
this.dom.style.transition = `${transformTransition},${
heightTransition ? `${heightTransition},` : ''
}${widthTransition}`;
}${widthTransition}`;
this.dom.style.transform = '';
this.dom.style.width = '';
this.dom.style.height = '';
}
});
}
};

private getCurrentDrawerSome = () => !Object.keys(currentDrawer).some(key => currentDrawer[key]);
private getCurrentDrawerSome = () =>
!Object.keys(currentDrawer).some(key => currentDrawer[key]);

private getLevelDom = ({ level, getContainer }: IDrawerChildProps) => {
if (windowIsUndefined) {
return;
}
const container = getContainer && getContainer();
const parent = container ? container.parentNode as HTMLElement : null;
const parent = container ? (container.parentNode as HTMLElement) : null;
this.levelDom = [];
if (level === 'all') {
const children: HTMLElement[] = parent ? Array.prototype.slice.call(parent.children) : [];
const children: HTMLElement[] = parent
? Array.prototype.slice.call(parent.children)
: [];
children.forEach((child: HTMLElement) => {
if (
child.nodeName !== 'SCRIPT' &&
Expand All @@ -420,7 +466,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
});
});
}
}
};

private getHorizontalBoolAndPlacementName = () => {
const { placement } = this.props;
Expand All @@ -430,7 +476,7 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
isHorizontal,
placementName,
};
}
};

// tslint:disable-next-line:member-ordering
public render() {
Expand Down Expand Up @@ -474,7 +520,8 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
const { placementName } = this.getHorizontalBoolAndPlacementName();
// 百分比与像素动画不同步,第一次打用后全用像素动画。
// const defaultValue = !this.contentDom || !level ? '100%' : `${value}px`;
const placementPos = placement === 'left' || placement === 'top' ? '-100%' : '100%';
const placementPos =
placement === 'left' || placement === 'top' ? '-100%' : '100%';
const transform = open ? '' : `${placementName}(${placementPos})`;

const handlerChildren =
Expand Down Expand Up @@ -531,7 +578,9 @@ class DrawerChild extends React.Component<IDrawerChildProps, IState> {
ref={c => {
this.contentDom = c as HTMLElement;
}}
onTouchStart={open && showMask ? this.removeStartHandler : undefined} // 跑用例用
onTouchStart={
open && showMask ? this.removeStartHandler : undefined
} // 跑用例用
onTouchMove={open && showMask ? this.removeMoveHandler : undefined} // 跑用例用
>
{children}
Expand Down

0 comments on commit e52ef83

Please sign in to comment.