React原生下拉刷新 上拉加载 图片预加载

首先配置好React   px转rem  这里是750转的   请注意!!!

js 页面的代码

import { Component } from 'react'
//引入数据接口 就是axios的二次封装
import { searchCar } from '../httpRequest/index'
//引入css样式
import './index.less'
class Index extends Component {
    constructor(...args) {
        super(...args);
        this.state = {
            CarList: [],
        }
        this.CountHeight = 0;
        this.CountImage = 0;
        this.LoadCount = 1
        this.LoadSwitch = true;
        this.CarImageList = [`http://www.ibugthree.com/default.gif`];
    }
    // 页面初始化
    async componentDidMount() {
        this.CarArray = await searchCar({ page: this.LoadCount, mod: '' })
        this.setState({
            CarList: this.CarArray
        });
        // 获取可视窗口高
        this.ViewHeight = document.documentElement.clientHeight;
        // 获取列表盒子的高
        this.ScrollHeight = this.refs['loadMore'].scrollHeight;
        // 用列表盒子的高除以数组的长度就是每一个列表的高度
        this.EveryHeight = this.ScrollHeight / this.CarArray.length;
        // 调用加载图片的方法
        this.FnSetHeight();
        // 做预加载的处理
        for (let i = 0; i < this.CarImageList.length; i++) {
            // 取出每一个图片路径
            let URL = this.CarImageList[i];
            // new 一个实例化  也就是图片预加载
            let Images = new Image();
            // 把图片地址放到new出来的img中
            Images.src = URL;
            Images.onload = function () {
                // 给加载的图片计数
                this.CountImage++;
                if (this.CountImage >= this.CarImageList.length) {
                    for (var i = 0; i < this.CountImage.length - 1; i++) {
                        let Car = this.CarArray[i];
                        Car.imageState = 1;
                    }
                    this.setState({
                        CarList: this.CarArray
                    })
                }
            }.bind(this);
        }
        document.onscroll = this.FnScroll.bind(this);
    }
    async FnScroll() {
        // 获取滚动到上面的距离
        this.ScrollTop = document.documentElement.scrollTop;
        // 获取列表盒子的高
        this.ScrollHeight = this.refs['loadMore'].scrollHeight;
 
        for (let i = 0; i < this.CarArray.length; i++) {
            let Car = this.CarArray[i];
            if (this.ScrollTop + this.ViewHeight >= Car.heights) {
                Car.imageState = 1;
            }
        }
        this.setState({
            CarList: this.CarArray
        })
        // 上拉加载更多
        if (this.ScrollTop + this.ViewHeight >= this.ScrollHeight) {
            // 添加开关 LoadSwitch 等于true的时候才能加载数据
            if (this.LoadSwitch) {
                // 页数加加
                this.LoadCount++;
                // 添加的时候为false
                this.LoadSwitch = false;
                // 获取数据
                let CarData = await searchCar({ page: this.LoadCount, mod: '' });
                // 将数据添加到数组中
                this.CarArray = this.CarArray.concat(CarData);
                // 数据添加到数组中说明数据已经请求出来了 所以让开关为false
                this.LoadSwitch = true;
                // 调用添加图片的方法
                this.FnSetHeight();
                // 将数据添加到要往页面上渲染的数中
                this.setState({
                    CarList: this.CarArray
                })
 
            }
        }
    }
    FnSetHeight() {
        // 循环请求出来的数据
        for (let i = 0; i < this.CarArray.length; i++) {
            // 把获取出来的数据赋值到Car
            let Car = this.CarArray[i];
            // 获取每一个距离顶部的距离  下标乘列表的高度  比如下标是0 0*160还是等于0   1*160等于160 所以第二个列表距离顶部的距离是160
            Car.heights = this.EveryHeight * i;
 
            this.CountHeight++;
            // 比较高度  判断Car.heights 如果小于等于可视窗口的高就说明这个列表显示出来
            if (this.ViewHeight >= Car.heights) {
                //获取数组里面的imageState  改变它的值为1
                Car['imageState'] = 1;
                // 将获取的图片路径添加到图片数组里面
                this.CarImageList.push(`http://www.ibugthree.com/${Car.img_src}`);
            } else {
                // 否则的就是没有到可视区窗口 就让他为0
                Car['imageState'] = 0;
            }
        }
    }
    FnImageState(item) {
        // 获取数据根据数据imageState值为1 就返回图片路径
        if (item.imageState) {
            return `http://www.ibugthree.com/${item.img_src}`;
        } else {
            // 否则还是默认的图片
            return `http://www.ibugthree.com/default.gif`;
        }
    }
    // 手指触发
    FnStart(ev) {
        this.refs['loadMore'].classList.remove("active");
        this.startY = ev.changedTouches[0].pageY;
        this.PageY =
            this.startY - this.refs.loadMore.getBoundingClientRect().top;
        document.ontouchmove = this.FnMove.bind(this)
        document.ontouchend = this.FnEnd.bind(this)
    }
 
    // 手指滑动
    FnMove(ev) {
        this.scrollTop = document.documentElement.scrollTop
        this.moveY = ev.changedTouches[0].pageY;
        if (this.moveY > this.startY && this.scrollTop == 0) {
            this.Y = this.moveY - this.PageY;
            this.scale = 1 - this.Y / 736;
            if (this.scale <= 0.58) this.scale = 0.58;
            this.refs.loadMore.style.transform = `translate(0,${this.Y * this.scale
                }px)`;
        }
    }
    // 手指抬起
    async FnEnd(ev) {
        this.UpY = ev.changedTouches[0].pageY;
        this.refs.loadMore.classList.add("active");
        if (this.scrollTop == 0) {
            this.refs.loading.style.display = 'block'
            this.refs.loadMore.style.transform = `translate(0,100px)`;
            setTimeout(() => {
                this.refs.loadMore.style.transform = `translate(0,0)`;
                this.refs.loading.style.display = 'none'
                this.componentDidMount()
            }, 2000)
        }
    }
    fn() {
    }
    render() {
        return (
            <div className="load-more">
                <div className="load-more-loading" ref='loading' onTouchMove={this.fn}></div>
                <div className='load-fixed' style={{ display: this.miek ? 'block' : 'none' }}>...loading</div>
                <div ref="loadMore" onTouchStart={this.FnStart.bind(this)} onTouchMove={this.FnMove.bind(this)} onTouchEnd={this.FnEnd.bind(this)}>
                    <div className="load-shadow"></div>
                    {this.state.CarList.map((item) => <div className="load-more-car" key={item.ID}>
                        <div className="load-more-item">
                            <div className="load-more-left">
                                <img className="load-more-kmr" src={this.FnImageState(item)} alt="a" />
                            </div>
                            <div className="load-more-right">
                                <div className="load-more-title">{item.tit_con}</div>
                                <div className="load-more-information">
                                    <div className="load-more-year">{item.buy_time}</div>
                                    <div className="load-more-line"></div>
                                    <div className="load-more-kilometre">{item.mileage}万公里</div>
                                </div>
                            </div>
                        </div>
                    </div>)}
                </div>
            </div>
        )
    }
 
}
export default Index

css 代码  less  布局

.load-more {
    position: relative;
 
    .load-more-loading {
        width: 80px;
        height: 80px;
        background: url('../img//loading.gif') no-repeat;
        background-size: cover;
        position: absolute;
        left: 0;
        right: 0;
        margin: auto;
        top: 30px;
        display: none;
        touch-action: none;
    }
}
 
.load-fixed {
    width: 100vw;
    height: 100vh;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 2;
    background: #fff;
    text-align: center;
    touch-action: none;
}
 
.load-more-car::after {
    display: block;
    content: "";
    width: 723px;
    height: 1px;
    background: #ededed;
    position: absolute;
    right: 0;
    margin: 42px 0 29px 0;
}
 
.load-more-car {
    position: relative;
 
    padding: 29px 0 0 0;
 
    .load-more-item {
        display: flex;
        flex-wrap: wrap;
 
        .load-more-left {
            padding: 0 0 0 14px;
            width: 249px;
            height: 187px;
 
            .load-more-kmr {
                width: 249px;
                height: 187px;
                border-radius: 10px;
            }
        }
 
        .load-more-right {
            padding: 0 0 0 19px;
 
            .load-more-title {
                width: 426px;
                font-size: 27px;
                color: #000;
                font-weight: bold;
            }
 
            .load-more-information {
                display: flex;
                color: #ababab;
                font-size: 19px;
                line-height: 19px;
                padding: 11px 0 0 0;
 
                .load-more-line {
                    width: 3px;
                    height: 19px;
                    background: #ababab;
                    margin: 0px 7px 0 8px;
                }
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值