react的预加载,上拉加载,下拉刷新,延迟加载

本文展示了如何使用React和CSS创建一个动态加载的页面,包括页面滚动监听、图片预加载以及上拉加载更多的功能。通过组件化和状态管理,实现了列表项的显示和隐藏,同时应用了CSS样式进行布局和动画效果。此外,还涉及到了触摸事件的处理,实现了平滑的滚动和加载体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

复制就可以用

这是css的代码


.zhuye {
    position: relative;
 
    
}
 

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


    img {
        position: absolute;
        width: 1000px;
        height: 700px;
        top: 50%;
        left: 50%;
        margin-top: -400px;
        margin-left: -500px;
    }
}
 
.load-more-car::after {
    display: block;
    content: "";
    width: 723px;
    height: 1px;
    background: #ededed;
    position: absolute;
    right: 0;
    margin: 42px 0 29px 0;
}

.active{
    transition: 0.15s ease-in all;

}
    .car {
        position: relative;
     
        padding: 40px 0 0 0;
    
      
     
        .load-more-item {
            display: flex;
            flex-wrap: wrap;
     
            .left {
                padding: 0 0 0 30px;
                width: 249px;
                height: 187px;
     
                .ccc {
                    width: 249px;
                    height: 187px;
                    border-radius: 10px;
                }
            }
     
            .right {
                padding: 0 0 0 19px;
     
                .more-title {
                    width: 426px;
                    font-size: 30px;
                    color: #000;
                    font-weight: bold;
                }
     
                .more-item {
                    display: flex;
                    color: #161212;
                    font-size: 19px;
                    line-height: 19px;
                    padding: 11px 0 0 0;
     
                    .buy {
                        width: 3px;
                        height: 19px;
                        background: #ababab;
                        margin: 0px 7px 0 8px;
                    }
                }
                .qian{
                    color: orange;
                    font-size: 20px;
                    margin-top: 20px;
                }
                .label{
                    display: flex;
                    margin-top: 10px;
                    .self-support{
                        display: inline;
                        width: 90px;
                        height: 24px;
                        line-height: 24px;
                        background: #e8d388;
                        border-radius: 3px;
                        font-size: 14px;
                        color: orange;
                        text-align: center;
                    }
                    .no-reason{
                        display: inline;
                        width: 130px;
                        height: 22px;
                        line-height: 22px;
                        text-align: center;
                        border: 2px solid orange;
                        font-size: 15px;
                        color: orange;
                        border-radius: 3px;
                        margin-left: 6px;
                    }
                    .new{
                        display: inline;
                        width: 65px;
                        height: 23px;
                        line-height: 23px;
                        text-align: center;
                        border: 2px solid orange;
                        font-size: 15px;
                        color: orange;
                        border-radius: 3px;
                        margin-left: 4px;
                    }
                }
            }
        }
    }
    

 

这是react的代码

import { Component } from 'react'
//引入数据接口 就是axios的二次封装
import { searchCar } from '../../api/index'
import load from '../../img/un.gif'
//引入css样式
import './holle.less'
class Index extends Component {
    constructor(...args) {
        super(...args);
        this.state = {
            CarList: [],
            load:'block'
        }
        this.CountHeight = 0;
        this.CountImage = 0;
        this.Loadpage = 1
        this.LoadSwitch = true;
        this.CarImageList = [`http://www.ibugthree.com/default.gif`];
    }
    // 页面初始化
    async componentDidMount() {
        this.CarArray = await searchCar({ page: this.Loadpage, mod: '' })
        this.setState({
            CarList: this.CarArray
        });
        // 获取可视窗口高
        this.ViewHeight = document.documentElement.clientHeight;
        // 获取列表盒子的高
        this.ScrollHeight = this.refs['fnMore'].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,
                        load:'none'
                    })
                }
            }.bind(this);
        }
        document.onscroll = this.FnScroll.bind(this);
    }
    async FnScroll() {
        // 获取滚动到上面的距离
        this.ScrollTop = document.documentElement.scrollTop;
        // 获取列表盒子的高
        this.ScrollHeight = this.refs['fnMore'].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.Loadpage++;
                // 添加的时候为false
                this.LoadSwitch = false;
                // 获取数据
                let CarData = await searchCar({ page: this.Loadpage, 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['fnMore'].classList.remove("active");
        this.startY = ev.changedTouches[0].pageY;
        this.PageY =
            this.startY - this.refs.fnMore.getBoundingClientRect().top;
        //     this.refs.fnMore.ontouchmove = this.FnMove.bind(this)
        //     this.refs.fnMore.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.fnMore.style.transform = `translate(0,${this.Y * this.scale
                }px)`;
        }
    }

    // 抬起
    async FnEnd(ev) {
        this.UpY = ev.changedTouches[0].pageY;
        this.refs.fnMore.classList.add("active");
        this.refs.loading.style.display = 'block'
        if (this.scrollTop == 0) {
            this.refs.loading.style.display = 'none'
            this.refs.fnMore.style.transform = `translate(0,0px)`;
            this.Loadpage++
            this.CarList = []
            this.CarList = await searchCar({ page: this.Loadpage, mod: '' })
            setTimeout(() => {
                this.refs.fnMore.style.transform = `translate(0,0)`;
                this.refs.loading.style.display = 'none'
                this.componentDidMount()
            }, 2000)
        }


    }

    render() {
        return (
            <div className="zhuye">
                <div className='loading' ref='loading' style={{ display: this.state.load }}>
                    <img src={load} alt="" />
                </div>
                <div className='load-fixed' style={{ display: this.Load ? 'block' : 'none' }}>...loading</div>
                <div ref="fnMore" onTouchStart={this.FnStart.bind(this)} onTouchMove={this.FnMove.bind(this)} onTouchEnd={this.FnEnd.bind(this)}>
                    <div className="shadow"></div>
                    {this.state.CarList.map((item) => <div className="car" key={item.ID}>
                        <div className="load-more-item">
                            <div className="left">
                                <img className="ccc" src={this.FnImageState(item)} alt=" " />
                            </div>
                            <div className="right">
                                <div className="more-title">{item.tit_con}</div>
                                <div className="more-item">
                                    <div className="year">{item.buy_time}</div>
                                    <div className="buy"></div>
                                    <div className="mileage">{item.mileage}万公里</div>
                                </div>
                                <div className="qian">首付4.63万</div>
                                <div className="label">
                                    {/* <!-- 自营 --> */}
                                    <div className="self-support">优惠自营</div>
                                    {/* <!-- 无理由 --> */}
                                    <div className="no-reason">七天无理由退车</div>
                                    <div className="new">95成新</div>
                                </div>
                            </div>
                        </div>
                    </div>)}
                </div>
            </div>
        )
    }

}
export default Index

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值