React中实现图片预加载、延迟加载、上拉加载、下拉更新

1.jsx代码

import { Component } from "react";
import '../List/list.less'
import { searchCar } from '../../api/index'
import love from '../../assets/search/爱心.gif';
import load from '../../assets/images(1)/loding.gif'

class List extends Component {
    constructor(...args) {
        super(...args)
        this.state = {
            list: [],
            load: 'block',
            Loading: false,
            flag: true
        }
        this.CarArray = []
        this.page = 1;
        this.ImgList = []
        this.CarCount = 0;
        this.ImageCount = 0; //计次(统计图片数量)
        this.count = 1;
    }
    // 接口方法
    async searchCar() {
        return await searchCar({
            page: this.page,
            mod: ''
        })
    }
    FnDate() {
        this.CarArray = []
        this.page = 1;
        this.ImgList = []
        this.CarCount = 0;
        this.ImageCount = 0; //计次(统计图片数量)
        this.count = 1;
    }
    // 钩子函数
    async componentDidMount() {
        await this.FnInit()
        // 监听个页面的滚动
        document.onscroll = this.FnDelayMore.bind(this);

    }
    // 图片预加载
    imgState(item) {
        if (item.imgState) {
            return `http://www.ibugthree.com/${item.img_src}`;
        } else {
            return `http://www.ibugthree.com/default.gif`;
        }
    }
    //设置高度
    // whether 0不需要 1需要 (设置图片)
    FnSetHeight(whether) {
        for (let i = 0; i < this.CarArray.length; i++) {
            let json = this.CarArray[i]; //每一条数据
            this.CarCount = this.EveryHeight * i; //每一条数据的高度
            json.height = this.CarCount; //每一条数据的高度添加到json中
            //  求出每个数据的高度
            if (this.CarCount > this.viewHeight) {
                //不需要加载的
                json.imgState = 0;
            } else {
                // 需要加载出来的
                json.imgState = 1;

                if (whether) {
                    //是否需要添加图片
                    let URL = `http://www.ibugthree.com/${json.img_src}`;
                    this.ImgList.push(URL);
                }
            }
        }
    }
    // 上拉加载更多
    async FnDelayMore() {
        this.CarArray = this.state.list
        // 延迟加载
        //可视区的高度
        this.viewHeight = document.documentElement.clientHeight;
        // 滚动高度
        this.roll = document.documentElement.scrollTop || document.body.scrollTop;
        // 滚动高度+可视区的高度 = 大于页面的高度
        this.ScrollHeight = this.roll + this.viewHeight;

        for (var i = 0; i < this.CarArray.length; i++) {
            let Car = this.CarArray[i];
            if (this.roll + this.viewHeight > Car.height) {
                Car.imgState = 1;

            }
        }
        this.setState({
            list: this.CarArray
        })
        // 加载更多
        if (
            this.ScrollHeight >= (this.refs.loadMore.scrollHeight - 1) && this.state.flag
        ) {
            this.setState({
                flag: false
            })
            this.count = 1;
            for (let i = 0; i < this.CarArray.length; i++) {
                var Img = new Image();
                let URL = `http://www.ibugthree.com/${this.CarArray[i].img_src}`; //图片地址
                Img.src = URL;
                Img.onload = async () => {
                    this.count++;
                    if (this.count >= this.CarArray.length) {
                        this.setState({
                            Loading: true,
                            flag: true
                        })
                        this.page++
                        let CarData = await this.searchCar();
                        this.CarArray = this.CarArray.concat(CarData);
                        // 所有的数据设置高度
                        this.FnSetHeight();

                        this.setState({
                            list: this.CarArray,
                            Loading: false
                        });
                    }
                }
            }

        }
    }


    // 预加载初始化
    async FnInit() {
        //重新加载接口
        this.CarArray = await this.searchCar();
        this.setState({
            list: this.CarArray
        });
        // 可视区的高度
        this.viewHeight = document.documentElement.clientHeight;
        // 滚动高度
        this.roll = document.documentElement.scrollTop || document.body.scrollTop;
        // 整体的高度
        this.EveryHeight = (this.refs['loadMore'].offsetHeight) / this.CarArray.length;
        this.FnSetHeight(1); //设置高度
        // 图片预加载
        this.ImgList.push("http://www.ibugthree.com/default.gif");
        for (let i = 0; i < this.ImgList.length; i++) {
            let oImage = new Image();
            let URL = this.ImgList[i]; //图片地址
            oImage.src = URL;
            oImage.onload = () => {
                this.ImageCount++;
                if (this.ImageCount >= this.ImgList.length) {
                    // 数据加载完成后改为false
                    this.setState({
                        list: this.CarArray,
                        load: 'none'
                    });

                }
            }
        }
    }

    //下拉刷新
    FnStart(ev) {
        this.refs.loadMore.classList.remove("active");
        this.startY = ev.changedTouches[0].pageY; //拖动的高度(鼠标距离顶部的距离)
        this.PageY = this.startY - this.refs.loadMore.getBoundingClientRect().top; //获取鼠标距离loadmore顶部的距离
        this.refs.loadMore.ontouchmove = this.FnMove.bind(this)
        this.refs.loadMore.ontouchend = this.FnEnd.bind(this)
    }
    FnMove(ev) {
    
        this.moveY = ev.changedTouches[0].pageY;
        // eslint-disable-next-line
        if (this.moveY > this.startY && this.roll == 0) {
            this.Y = this.moveY - this.PageY - 110; //向下移动的值
            this.scale = 1 - this.Y / 736;
            if (this.scale <= 0.54) {
                this.scale = 0.54;
            }
            this.refs.loadMore.style.transform = `translate(0,${this.Y * this.scale
                }px)`;
            ev.preventDefault && ev.preventDefault();
        }
        this.setState({
            load: 'block'
        })


    }
    async FnEnd(ev) {
        this.UpY = ev.changedTouches[0].pageY;
        this.refs.loadMore.classList.add("active");
        this.refs.loadMore.style.transform = `translate(0,0)`;
        this.CarArray = this.state.list
        ev.preventDefault && ev.preventDefault();

        // eslint-disable-next-line
        if (this.UpY > this.startY && this.roll == 0) {
            //所有数据恢复初始状态
            this.FnDate();
            this.setState({
                list: this.CarArray
            });
            this.state.list = await this.searchCar();
            //图片预加载 设置高度
            await this.FnInit();
            this.setState({
                load: 'none'
            })
        }
    }


    render() {
        return (
            <div>
                {/* <列表 */}
                <div className="list" ref='loadMore' onTouchStart={this.FnStart.bind(this)}>
                    <div className="list-ul" >
                        {this.state.list.map((item) => <div className="list-li" key={item.ID}>
                            <img src={love} alt="" className="love" />
                            {/* eslint-disable-next-line */}
                            <img src={this.imgState(item)} className="car" />
                            <div className="list-content">
                                <div className="list-title">
                                    {item.tit_con}
                                div>
                                <div className="car-year">
                                    <div className="year">{item.buy_time}|div>

                                    <div className="kilometre">{item.kilometre}万公里div>
                                div>
                                <div className="car-price">
                                    <div className="present-price">{item.nal_price}万div>
                                    <div className="down-payments">首付{item.down_payments}万div>
                                div>

                                <div className="label">
                                    <div className="self-support">优惠自营div>
                                    <div className="no-reason">七天无理由退车div>
                                    <div className="new">95成新div>
                                div>
                            div>
                        div>)}
                        <div className="loading" style={{ display: this.state.Loading }}>Loading...div>
                        {/* 加载 */}
                        <div className='load' style={{ display: this.state.load }}>
                            <img src={load} alt="" />
                        div>
                    div>
                div>
            div>
        )
    }
}
export default List

css样式

// css初始化
body {
    margin: 0;
}

/* 去掉a的下划线 */
a {
    text-decoration: none;
}

/* 搜索框去除边框 */
input {
    border: 0;
    /* 设置背景颜色为透明 */
    background-color: transparent;
    /* 去掉外轮廓 */
    outline: none;
}

/* 图片的空白间隙 */
img {
    vertical-align: middle;
}

// css初始化结束
// 列表
.list {
    position: relative;
    z-index: 5;
    width: 750px;

    .list-ul {
        width: 750px;

        .loading {
            width: 750px;
            height: 40px;
            line-height: 40px;
            text-align: center;
            font-size: 30px;
            background: #fff;
            color: #ccc;
        }

        .list-li {
            position: relative;
            width: 750px;
            height: 258px;
            border-bottom: 1px solid #e8e8e8;
            display: flex;
            align-items: center;
            justify-content: space-around;
            box-sizing: border-box;

            .love {
                position: absolute;
                width: 30px;
                height: 26px;
                top: 97px;
                right: 26px;
            }

            // 图片
            .car {
                width: 248px;
                height: 187px;
                line-height: 187px;
                border-radius: 10px;
                padding-left: 15px;
                margin-right: 19px;
            }

            // 内容
            .list-content {
                display: flex;
                flex-direction: column;
                height: 180px;
                width: 430px;
                box-sizing: border-box;
                margin-top: -20px;

                // 标题
                .list-title {
                    font-size: 26px;
                    height: 60px;
                    line-height: 40px;
                    color: #272727;
                    font-weight: 700;
                    box-sizing: border-box;
                }

                // 公里数
                .car-year {
                    padding-top: 21px;
                    width: 100%;

                    .year {
                        display: inline;
                        font-size: 19px;
                        color: #989898;
                    }

                    .kilometre {
                        display: inline;
                        font-size: 14px;
                        color: #9c9c9c;
                        padding-left: 5px;
                    }
                }

                // 价格
                .car-price {
                    width: 100%;
                    margin-top: 10px;

                    .present-price {
                        display: inline;
                        font-size: 25px;
                        color: #d96736;
                    }

                    .down-payments {
                        display: inline;
                        font-size: 21px;
                        color: #b3b3b3;
                        margin-left: 7px;
                    }
                }

                // 标签
                .label {
                    width: 100%;
                    height: 24px;
                    margin-top: 10px;
                    display: flex;
                    align-items: center;

                    .self-support {
                        display: inline;
                        height: 24px;
                        line-height: 24px;
                        background-image: linear-gradient(to right, #f0e6b1, #edb573);
                        border-radius: 3px;
                        font-size: 14px;
                        color: #774e04;
                        text-align: center;
                        margin-right: 6px;
                        padding: 2px 4px;
                    }

                    .no-reason {
                        display: inline;
                        height: 20px;
                        line-height: 23px;
                        text-align: center;
                        border: 1px solid #f93300;
                        font-size: 15px;
                        color: #f93300;
                        border-radius: 3px;
                        margin-right: 5px;
                        padding: 2px 4px;
                    }

                    .new {
                        display: inline;
                        height: 20px;
                        line-height: 23px;
                        text-align: center;
                        border: 1px solid #f93300;
                        font-size: 15px;
                        color: #f93300;
                        border-radius: 3px;
                        padding: 2px 4px;
                    }
                }
            }
        }
    }

    // loading加载页
    .load {
        width: 100vw;
        height: 100vh;
        background: #fff;
        position: fixed;
        top: 0;
        left: 0;
        z-index: 999;

        img {
            position: absolute;
            width: 200px;
            height: 200px;
            top: 50%;
            left: 50%;
            margin-top: -100px;
            margin-left: -100px;
        }
    }
}

你可能感兴趣的:(react,css,react.js,javascript)