perf: optimize the rendering animation and layer sequence of withKeepAliveOverlay

pull/90/head
moonrailgun 2 years ago
parent add116cffc
commit f09930796b

@ -1,6 +1,7 @@
import React, { useEffect, useMemo, useRef } from 'react';
import { useKeepAliveStore } from './store';
import _omit from 'lodash/omit';
import { createRAFLoop, getDOMParentPath } from '@/utils/dom-helper';
/**
*
@ -49,6 +50,7 @@ export function withKeepAliveOverlay<
return;
}
// resize
const resizeObserver = new ResizeObserver((entries) => {
entries.forEach((entry) => {
const { target } = entry;
@ -66,12 +68,41 @@ export function withKeepAliveOverlay<
});
});
});
resizeObserver.observe(containerRef.current);
// transition
const parentPath = getDOMParentPath(containerRef.current);
function update(e: TransitionEvent) {
if (
containerRef.current &&
parentPath.includes(e.target as HTMLElement)
) {
// 父节点有触发 transition 事件,则更新容器节点大小
const rect = containerRef.current.getBoundingClientRect();
updateRect(cacheId, {
left: rect.left,
top: rect.top,
width: rect.width,
height: rect.height,
});
}
}
/**
* use raf to make sure smooth animation
*/
const { start: handleTransitionStart, end: handleTransitionEnd } =
createRAFLoop(update);
window.addEventListener('transitionend', handleTransitionEnd);
window.addEventListener('transitionstart', handleTransitionStart);
return () => {
if (containerRef.current) {
resizeObserver.unobserve(containerRef.current);
window.removeEventListener('transitionend', handleTransitionEnd);
window.removeEventListener('transitionstart', handleTransitionStart);
}
};
}, [cacheId]);

@ -105,7 +105,8 @@ export const PageContent: React.FC<PropsWithChildren<PageContentProps>> =
const contentMaskEl = showMask ? (
<div
className="absolute left-0 top-0 bottom-0 right-0 z-10"
className="absolute right-0 top-0 bottom-0 z-10"
style={{ width: 'calc(100% - 15rem)' }} // 15rem is "w-60" which sidebar with
onClick={handleHideSidebar}
/>
) : null;
@ -116,9 +117,11 @@ export const PageContent: React.FC<PropsWithChildren<PageContentProps>> =
<ErrorBoundary>
{sidebarEl}
{contentMaskEl}
<div
className={clsx(
'flex flex-auto bg-content-light dark:bg-content-dark overflow-hidden z-10',
'flex flex-auto bg-content-light dark:bg-content-dark overflow-hidden',
isMobile &&
'transform left-0 w-full h-full absolute transition-transform',
isMobile && {
@ -136,8 +139,6 @@ export const PageContent: React.FC<PropsWithChildren<PageContentProps>> =
'overflow-hidden': showMask,
})}
>
{contentMaskEl}
<ErrorBoundary>{contentEl}</ErrorBoundary>
</div>
</div>

@ -24,3 +24,52 @@ export function stopPropagation(e: React.BaseSyntheticEvent) {
export function preventDefault(e: React.BaseSyntheticEvent) {
e.preventDefault();
}
/**
* DOM
*/
export function getDOMParentPath(el: HTMLElement): HTMLElement[] {
const path: HTMLElement[] = [];
let parent = el.parentElement;
while (parent) {
path.unshift(parent);
parent = parent.parentElement;
}
return path;
}
/**
* RAF
* @param loopFn
* @returns
*/
export function createRAFLoop<T extends unknown[]>(
loopFn: (...args: T) => void
) {
let flag = false;
const loop = (...args: T) => {
if (flag === false) {
return;
}
loopFn(...args);
requestAnimationFrame(() => {
loop(...args);
});
};
return {
start: (...args: T) => {
flag = true;
loop(...args);
},
end: () => {
requestAnimationFrame(() => {
flag = false;
});
},
};
}

@ -30,7 +30,7 @@ const tailchat = plugin(({ e, addUtilities }) => {
right: 0,
height: '1px',
boxShadow: customTheme.boxShadow.elevationLow,
zIndex: 1,
// zIndex: 1,
pointerEvents: 'none',
},
},

Loading…
Cancel
Save