Skip to content

Commit

Permalink
🐛 fix(custom): 修复eu都在溜什么页面渲染时间过长的bug,同时统一所有图片的加载过渡效果
Browse files Browse the repository at this point in the history
  • Loading branch information
master1lan committed Mar 30, 2023
1 parent 70aa014 commit f201cd1
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 245 deletions.
130 changes: 61 additions & 69 deletions src/components/image/index.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,68 @@
import { useCallback, useMemo, useState, memo, ReactElement } from "react";
import { InView } from "react-intersection-observer";
import { useCallback, ReactElement, useEffect, useState } from "react";
import { useInView } from "react-intersection-observer";
import { Once } from "@utils/index";
import { ImageProps } from "./imagetype";
import styles from "./image.module.less";
import {
getImageSize,
getResizeHeight,
fallbackUrl as DefaultFallbackUrl,
ImageSize,
} from "./tool";
import { styled } from "@mui/material";

/**
* @description 图片预加载hook
*/

function useLoading(url: string) {
const [obj, setObj] = useState<ImageSize & { isLoaded: boolean }>({
width: 0,
height: 0,
again: false,
isLoaded: false,
success: true,
});
useMemo(async () => {
const res = await getImageSize(url);
setObj(() => ({ ...res, isLoaded: true }));
}, [url]);
return obj;
}

/**
*@description 图片组件库,默认支持图片加载fallback。
*/

export default memo(function Image({
import { styled } from "@mui/material";
import { fallbackUrl, getImageSize } from "./tool";
export function InviewImage({
url,
width = 200,
height,
fallbackUrl = DefaultFallbackUrl,
observer,
callback,
children,
title,
...resProps
}: ImageProps & {
title: string;
children?: ReactElement;
[k: string]: any;
}) {
const res = useLoading(url),
{ isLoaded, success } = res,
real_width = width,
real_height = height || getResizeHeight(res, real_width),
real_fallback_url = fallbackUrl || DefaultFallbackUrl;
const [isImgLoading, setImgLoading] = useState(true);
const once_callback = useCallback(Once(callback!!), []);
const { ref, inView, entry } = useInView();
const [onceInView, setOnceInView] = useState(inView);
useEffect(() => {
if (inView) {
setOnceInView(() => true);
}
}, [inView]);
useEffect(() => {
if (observer && inView) {
once_callback(inView);
}
}, [inView, observer]);
useEffect(() => {
const handler = async () => {
await getImageSize(url);
setImgLoading(() => false);
};
onceInView && handler();
}, [onceInView]);
return (
<InView>
{({ inView, ref, entry }) => (
<BorderDiv ref={ref} className={styles.imgWrapper}>
<img
width={real_width}
height={real_height}
src={isLoaded && success ? url : real_fallback_url}
style={{
opacity: isLoaded ? 1.0 : 0.09,
}}
alt=''
loading='lazy'
/>
<>{observer && inView && once_callback(inView)}</>
{children}
</BorderDiv>
)}
</InView>
<BorderDiv ref={ref} className={styles.imgWrapper}>
<img
src={onceInView ? url : fallbackUrl}
alt={title}
loading='lazy'
{...resProps}
/>
<span
className={`absolute left-0 top-0 right-0 bottom-0 transition-all ${
isImgLoading ? "pointer-events-auto" : "pointer-events-none"
}`}
style={{
zIndex: 1,
transitionDuration: "400ms",
background: isImgLoading ? "hsla(0,0%,91.4%,.5)" : "transparent",
backdropFilter: !isImgLoading ? "blur(0)" : "blur(42.5px)",
WebkitBackdropFilter: !isImgLoading ? "blur(0)" : "blur(42.5px)",
}}
/>
{children}
</BorderDiv>
);
});
}

export function ImageBasic({
url,
Expand All @@ -86,16 +77,17 @@ export function ImageBasic({
[k: string]: any;
}) {
const once_callback = useCallback(Once(callback!!), []);
const { ref, inView, entry } = useInView();
useEffect(() => {
if (observer && inView) {
once_callback(inView);
}
}, [inView, observer]);
return (
<InView>
{({ inView, ref, entry }) => (
<BorderDiv ref={ref} className={styles.imgWrapper}>
<img src={url} alt={title} loading='lazy' {...resProps} />
<>{observer && inView && once_callback(inView)}</>
{children}
</BorderDiv>
)}
</InView>
<BorderDiv ref={ref} className={styles.imgWrapper}>
<img src={url} alt={title} loading='lazy' {...resProps} />
{children}
</BorderDiv>
);
}

Expand Down
72 changes: 0 additions & 72 deletions src/components/masonry/index.tsx

This file was deleted.

5 changes: 5 additions & 0 deletions src/normalize.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ body {
margin: 0;
}

html,
body {
scroll-behavior: smooth;
}

/**
* Render the `main` element consistently in IE.
*/
Expand Down
10 changes: 7 additions & 3 deletions src/routers/layout/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { Flipped, Flipper } from "react-flip-toolkit";
import { Outlet, useMatch } from "react-router-dom";
import { Outlet, useLocation, useMatch } from "react-router-dom";
import Header from "./header";
import { useAppSelector } from "@store/hooks";
import { selectNavMoreShowed } from "@store/device/index";
import ArrowOutwardIcon from "@mui/icons-material/ArrowOutward";
import { Link } from "@mui/material";

import styles from "./layout.module.less";
import Header_Nav from "./nav";
import { useEffect } from "react";
export default function Layout() {
const showed = useAppSelector(selectNavMoreShowed);
const location = useLocation();
useEffect(() => {
window.scrollTo({ top: 0 });
}, [location.pathname, location.search]);
return (
<>
<Flipper
Expand Down
13 changes: 10 additions & 3 deletions src/routers/layout/rightMore/euLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useScreenSize } from "@components/proview/screenSize";
import { Button } from "@mui/material";
import { useGetEuFetchParmas, useSetEuFetchParamas } from "@store/euWhatLook";
import {
useGetEuFetchParmas,
useGetEuIsloading,
useSetEuFetchParamas,
} from "@store/euWhatLook";
import { IFetchEUWhatLookIngParmas } from "@utils/fetch/eu6type";
import React from "react";
import { Link, useMatch } from "react-router-dom";
Expand Down Expand Up @@ -53,16 +57,19 @@ const OrderSort = () => {
const curParmas = useGetEuFetchParmas();
const filterItem = OrderItemLists.filter((item) => item.param !== curParmas);
const curItem = OrderItemLists.filter((item) => item.param === curParmas);
const isLoading = useGetEuIsloading();
const updateParamer = useSetEuFetchParamas(),
handleUpdateParmas = () => updateParamer(filterItem[0].param);
return (
<div>
{curItem.map((item) => (
<button
className='px-4 py-2 rounded-sm hover:bg-gray-200 transition-all duration-200'
className={`px-4 py-2 rounded-sm hover:bg-gray-200 transition-all duration-200 ${
isLoading ? "cursor-wait" : "cursor-pointer"
}`}
type='button'
key={item.label}
onClick={handleUpdateParmas}
onClick={isLoading ? undefined : handleUpdateParmas}
title={`当前排序规则`}
>
{item.label}
Expand Down
74 changes: 67 additions & 7 deletions src/routers/online/content.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,63 @@
import { Skeleton, Unstable_Grid2 as Grid } from "@mui/material";
import { FC, memo } from "react";
import { FC, memo, useState, useEffect, useCallback, useMemo } from "react";
import OnlineItem, { OnlineItemProps } from "./item";
import { useGetEuData } from "@store/euWhatLook/index";
export default function Index() {

const handerSetRenderData = (
newData: OnlineItemProps[],
callback: (inView: boolean) => void
) => {
const lastItem = newData[newData.length - 1];
if (lastItem) {
lastItem.observer = true;
lastItem.callback = callback;
}
return newData;
};

const useOnlineRenderData = () => {
//todo 测试
const { isLoading, data } = useGetEuData(10000000);
//分级渲染
const [renderData, setRednerData] = useState<OnlineItemProps[]>([]);
const [isRenderEd, setRenderEd] = useState(false);
const handleLazyLoadData = useMemo(() => {
const dataLen = data.length;
let curPage = 0;
const handler = () =>
setRednerData((curData) => [
...curData,
...handerSetRenderData(
data.slice(curPage * 20, (curPage + 1) * 20),
handleLazyLoadData
),
]);
return () => {
curPage++;
if ((curPage + 1) * 20 >= dataLen) {
setRenderEd(() => true);
}
if (curPage * 20 >= dataLen) {
return;
}
handler();
};
}, [isLoading, data, setRednerData, setRenderEd]);
useEffect(() => {
if (isLoading) {
setRednerData(() => []);
setRenderEd(() => false);
} else {
setRednerData(() =>
handerSetRenderData(data.slice(0, 20), handleLazyLoadData)
);
}
}, [isLoading, data]);
return { isLoading, renderData, isRenderEd };
};

export default function Index() {
const { isLoading, renderData } = useOnlineRenderData();
return (
<Grid
className='mt-2'
Expand All @@ -23,19 +76,26 @@ export default function Index() {
xs: 4,
}}
>
{isLoading &&
Array.from({ length: 20 }).map((item, key) => (
<LoadingItem key={key} />
))}
{!isLoading && data.map((item) => <MemoItem key={item.bvid} {...item} />)}
{!isLoading &&
renderData.map((item) => <MemoItem key={item.bvid} {...item} />)}
{isLoading && <LoadingCom />}
</Grid>
);
}

const MemoItem: FC<OnlineItemProps> = memo((props) => (
<Grid xs={2}>
<OnlineItem {...props} />
</Grid>
));
const fakeLoadingArray = Array.from({ length: 20 });
const LoadingCom = memo(() => (
<>
{fakeLoadingArray.map((_, index) => (
<LoadingItem key={index} />
))}
</>
));
const LoadingItem = () => (
<Grid xs={2}>
<div className='flex flex-col h-full'>
Expand Down
Loading

0 comments on commit f201cd1

Please sign in to comment.