首先配置好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;
}
}
}
}
}