Permalink
  
  
  
      
        
          
            
          
            
          
        
       
    
      
          
      
 
  
    
  
  
    
      
    
    
      
       
    
    
       
      Cannot retrieve contributors at this time
    
 
  
    
      
  
  
      
    
        
  
  
        
  
    
    
  
  
  Name already in use
      A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
    eoefans-web/src/routers/video/masonry.tsx
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
  
      131 lines (130 sloc)
      
    3.57 KB
  
  
    
  
    
      This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | import { fetchVideos } from "@utils/fetch"; | |
| import { Pick } from "@utils/index"; | |
| import { useState, useEffect, FC, memo } from "react"; | |
| import { VideoRouterImageCardType } from "./videotype"; | |
| import { Unstable_Grid2 as Grid } from "@mui/material"; | |
| import ImageShouldResizeProview from "@components/proview/imageSize"; | |
| import { VideoRouterImageCard } from "./item"; | |
| import { Skeleton } from "@mui/material"; | |
| import { nanoid } from "nanoid"; | |
| import styles from "./video.module.less"; | |
| /** | |
| * @description 该组件负责渲染视频图片的瀑布流 | |
| */ | |
| export default function VideoMasonry(props: { q?: string }) { | |
| const [lists, setLists] = useState< | |
| (VideoRouterImageCardType & { id: string })[] | |
| >([]); | |
| const [isLoading, setLoading] = useState<boolean>(true); | |
| useEffect(() => { | |
| // 在内部定义fetchHandler,保证拿到的是同步的 | |
| const fetchHandler = async (page: number = 1) => { | |
| const res = await fetchVideos({ | |
| order: "view", | |
| page, | |
| q: props.q, | |
| }), | |
| data = res.data.result; | |
| setLists((lists) => [ | |
| ...lists, | |
| ...data.map((item, index) => { | |
| const itemRes: VideoRouterImageCardType = Pick( | |
| item, | |
| "title", | |
| "bvid", | |
| "name", | |
| "tname", | |
| "copyright", | |
| "pic", | |
| "tag", | |
| "view", | |
| "coin", | |
| "share", | |
| "like", | |
| "pubdate", | |
| "danmaku", | |
| "duration", | |
| "favorite", | |
| "face" | |
| ); | |
| if (index === data.length - 3) { | |
| return { | |
| ...itemRes, | |
| id: nanoid(4), | |
| observer: true, | |
| callback: (inView: boolean) => { | |
| fetchHandler(page + 1); | |
| }, | |
| }; | |
| } | |
| return { ...itemRes, id: nanoid(4) }; | |
| }), | |
| ]); | |
| }; | |
| setLists([]); | |
| setLoading(true); | |
| fetchHandler(1).then(() => setLoading(false)); | |
| }, [props]); | |
| return ( | |
| <div className='feedContainer'> | |
| <ImageShouldResizeProview> | |
| <Grid | |
| container | |
| spacing={{ | |
| lg: 2, | |
| md: 1, | |
| sm: 1, | |
| xs: 1, | |
| }} | |
| columns={{ | |
| lg: 10, | |
| md: 8, | |
| sm: 6, | |
| xs: 4, | |
| }} | |
| > | |
| {lists.map((item) => ( | |
| <MemoItems key={item.id} {...item} /> | |
| ))} | |
| {isLoading && <LoadingSkeleton num={20} />} | |
| </Grid> | |
| </ImageShouldResizeProview> | |
| </div> | |
| ); | |
| } | |
| const MemoItems: FC<VideoRouterImageCardType> = memo((props) => { | |
| return ( | |
| <Grid xs={2}> | |
| <VideoRouterImageCard data={props} /> | |
| </Grid> | |
| ); | |
| }); | |
| const LoadingSkeleton: FC<{ num: number }> = ({ num = 0 }) => { | |
| return ( | |
| <> | |
| {...Array.from({ length: num }, (v, key) => ( | |
| <Grid xs={2} key={key}> | |
| <Skeleton | |
| variant='rounded' | |
| animation='wave' | |
| className={styles["skeleton-img"]} | |
| /> | |
| <Skeleton animation='wave' height={20} /> | |
| <Skeleton animation='wave' width={"50%"} height={20} /> | |
| <div className={styles["skeleton-content"]}> | |
| <Skeleton | |
| variant='circular' | |
| animation='wave' | |
| width={40} | |
| height={40} | |
| /> | |
| <div className={styles["skeleton-info"]}> | |
| <Skeleton animation='wave' width={"80%"} height={20} /> | |
| <Skeleton animation='wave' width={"80%"} height={20} /> | |
| </div> | |
| </div> | |
| </Grid> | |
| ))} | |
| </> | |
| ); | |
| }; |