ReactHook + Ts实现预加载和上拉加载

index.tsx

import React, { useEffect, useRef, useState } from 'react'
import "./index.less";
import { getSearchCar } from "./../../api/index";
interface carList {
    ID: number;
    card_time: string;
    tit_con: string;
    nal_price: string;
    img_src: string;
    vehicle_system: string;
    mileage: string;
    car_price: string
}
export default function YouXin() {
    const [title, settit] = useState<carList[]>([]);
    let count = 0
    let page = 1
    const Preload = useRef<HTMLDivElement>(null);
    const scrollpage = useRef<HTMLDivElement>(null);
    const Loading = useRef<HTMLDivElement>(null);
    const getload = () => Preload.current as HTMLDivElement;
    const getpage = () => scrollpage.current as HTMLDivElement;
    const getding = () => Loading.current as HTMLDivElement;
    useEffect(() => {
        (async () => {
            let carLists: carList[] = await getSearchCar({ page: "1", mod: "大众" });
            settit([...carLists]);
            for (var i = 0; i < carLists.length; i++) {
                let oimage = new Image();
                oimage.src = `后端接口地址/${carLists[i].img_src}`;
                oimage.onload = () => {
                    count++;
                    console.log(count);
                    if (count === carLists.length) {
                        getload().style.display = "none";
                    }
                }
            }
        })();
    }, []);
    const Fnscroll = async () => {
        let scrollTop = getpage().scrollTop;
        let viewHeight = getpage().clientHeight;
        let scrollHeight = getpage().scrollHeight;
        if (Math.trunc(scrollTop + viewHeight) === scrollHeight) {
            page++;
            let pagelist: carList[] = await getSearchCar({ page: `${page}`, mod: "大众" });
            getding().style.display = "block";
            setTimeout(() => {
                (getding().children[1] as HTMLDivElement).innerText = "加载成功";
                setTimeout(() => {
                    settit([...title, ...pagelist]);
                    getding().style.display = "none";
                    (getding().children[1] as HTMLDivElement).innerText = "加载中";
                }, 500);
            }, 1500);
        }
    }
    return (
        <div className="youxin-Body-Box">
            <div className="Preload" ref={Preload}>
                <img src={require("./../../images/tucheng.png")} alt="" />
            </div>
            <div className="youxin-BodyBox-header">
                <div>
                    <img src={require("./../../images/youxin-icon_03.jpg")} alt="" />全自营 更放心
                </div>
                <img src={require("./../../images/youxin-icon_06.jpg")} alt="" />
            </div>
            <div className="youxin-BodyBox-sort">
                <div>综合排序 <img src={require("./../../images/youxin-icon_15.jpg")} alt="" /></div>
                <div>品牌 <img src={require("./../../images/youxin-icon_21.jpg")} alt="" /></div>
                <div>价格 <img src={require("./../../images/youxin-icon_21.jpg")} alt="" /></div>
                <div>筛选 <img src={require("./../../images/youxin-icon_18.jpg")} alt="" /> </div>
            </div>
            <div className="youxin-BodyBox-content" ref={scrollpage} onScroll={Fnscroll}>
                <div className="youxin-BodyBox-List">
                    {title.map((item, index) => <div className='carList-item' key={item.ID}>
                        <img src={`http://www.ibugthree.com/${item.img_src}`} alt="" />
                        <div className=" carList-item-rightBox">
                            <div className="item-title">
                                {item.vehicle_system}
                            </div>
                            <div className="item-details">
                                {item.tit_con}
                            </div>
                            <div className="item-parameter">
                                <div>{item.card_time}上牌</div>
                                <div>{item.mileage}万公里</div>
                            </div>
                            <div className="item-Price">
                                <span>{item.nal_price.substring(0, 2)}</span>{item.nal_price.substring(2, 5)}万 首付
                                {item.car_price}万
                            </div>
                        </div>
                    </div>)}

                    <div className="Loading" ref={Loading}>
                        <img src={require("./../../images/upload.gif")} alt="" /><span>加载中...</span>
                    </div>
                </div>
            </div >
        </div >
    )
}

index.less

.youxin-Body-Box {
    width: 100vw;
    height: 100vh;
    background: #fff;
    display: flex;
    flex-direction: column;
    overflow: hidden;

    @keyframes turn {
        0% {
            -webkit-transform: rotate(0deg);
        }

        25% {
            -webkit-transform: rotate(90deg);
        }

        50% {
            -webkit-transform: rotate(180deg);
        }

        75% {
            -webkit-transform: rotate(270deg);
        }

        100% {
            -webkit-transform: rotate(360deg);
        }
    }

    .Preload {
        width: 100vw;
        height: 100vh;
        position: fixed;
        left: 0;
        top: 0;
        background-color: #fff;

        >img {
            display: block;
            width: 60px;
            height: 60px;
            margin: 370px auto;
            animation: turn 1s linear infinite
        }
    }

    .youxin-BodyBox-header {
        width: 100vw;
        height: 100px;
        display: flex;
        align-items: center;
        justify-content: space-between;
        background: #f7f8fa;

        >div {
            width: 250px;
            height: 33px;
            font-size: 27px;
            margin-left: 27px;
            line-height: 33px;
            font-weight: 900;

            >img {
                width: 21px;
                height: 33px;
                margin-right: 28px;
                vertical-align: middle;
            }
        }

        >img {
            width: 38px;
            height: 30px;
            margin-right: 29px;
        }
    }

    .youxin-BodyBox-sort {
        width: 100vw;
        height: 100px;
        display: flex;
        justify-content: space-around;
        font-size: 23px;

        >div {
            height: 100px;
            line-height: 100px;

            >img {
                margin-left: 9px;
                vertical-align: middle;
            }

            &:nth-child(1) {
                img {
                    width: 13px;
                    height: 18px;
                }
            }

            &:nth-child(2),
            &:nth-child(3) {
                img {
                    width: 14px;
                    height: 8px;
                }
            }

            &:nth-child(4) {
                img {
                    width: 15px;
                    height: 18px;
                }
            }
        }
    }

    .youxin-BodyBox-content::-webkit-scrollbar {
        display: none;
    }

    .youxin-BodyBox-content {
        width: 100vw;
        flex: 1;
        overflow-y: scroll;
    }

    .youxin-BodyBox-List {
        width: 100vw;
        display: block;

        .carList-item {
            margin: auto;
            width: 695px;
            height: 187px;
            display: flex;
            margin-top: 64px;

            &:nth-child(1) {
                margin-top: 0px;
            }

            >img {
                width: 247px;
                height: 187px;
            }

            .carList-item-rightBox {
                width: 422px;
                height: 187px;
                margin-left: 23px;

                .item-details {
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                    width: 100%;
                    font-size: 25px;
                    margin-bottom: 12px;
                }

                .item-title {
                    width: 100%;
                    font-size: 27px;
                    font-weight: 900;
                    margin-top: 12px;
                }

                .item-parameter {
                    height: 30px;
                    display: flex;
                    font-size: 19px;
                    margin-bottom: 28px;

                    >div {
                        padding: 0 15px 0 15px;
                        background: #f3f3f3;
                        margin-right: 8px;
                    }
                }

                .item-Price {
                    width: 100%;
                    font-size: 23px;
                    color: #ed713c;

                    >span {
                        font-size: 29px;
                        font-weight: 800;
                    }
                }
            }
        }

        .Loading {
            width: 100vw;
            height: 50px;
            display: flex;
            text-align: center;
            line-height: 50px;
            justify-content: center;
            align-items: center;
            display: none;
            font-size: 20px;

            >img {
                vertical-align: middle;
            }
        }
    }
}

 预加载:对求出的数据进行循环,创建 img对象,用onload事件监听,声明一个计数的变量,没加载完成一个img对象,就 ++;然后判断计数的量和请求过来的数据length是否相等,相等就把遮罩层隐藏,

上拉加载: 1.求出滚动元素的scrollTop 

                2.求出可视区高度

                3.求出滚动元素的滚动高度

                 判断 当 scroll + 可视区高度时 等于 滚动高度时就证明你此时必然触底,此时我们有一个保存页数的变量page  ,在我们触底后 page 就+ 1;然后我们求取新一页的数据,然后将上一页和新求取的一页数据合并,达成上拉加载功能,具体一些细节上的问题可以自行更高,仅提供一个构思;

如有高见,可在评论发言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Hooks是React 16.8引入的一种新的特性,可以让我们在函数组件中使用状态(state)和其他React特性。引用中的代码示例展示了如何在函数组件中使用React Hooks。在这个示例中,我们使用了useState来定义和管理组件的状态,使用了useEffect来处理副作用。useState接收一个初始值,并返回一个状态值和一个更新状态的函数。useEffect接收一个副作用函数和一个依赖数组,当依赖数组中的值发生变化时,副作用函数会被执行。这个示例还展示了如何使用React.FC类型来定义函数组件的props类型。在函数组件中,我们可以直接使用props来获取传入的属性值。 另外,引用中的命令 npx create-react-app ts-with-react --typescript 是用于创建一个React项目,并且使用TypeScript作为开发语言的。这个命令会自动创建一个基础的React项目结构,包括配置文件和示例代码。 如果你想在React项目中使用TypeScript,你需要确保已经安装了TypeScript和相关的开发工具。另外还可以使用yarn add cross-env命令安装cross-env包,用于在不同的环境中设置环境变量。修改package.json文件的scripts字段,可以设置启动、构建和测试等命令。通过运行yarn start命令,你可以启动React项目并在本地主机上运行。 总而言之,React Hooks是一种方便在函数组件中使用状态和其他React特性的方式。可以通过在函数组件中使用useState和useEffect来定义和管理状态以及处理副作用。同时,使用React.FC类型可以方便地定义函数组件的属性类型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值