上拉刷新下拉加载更多
vue好多插件可以使用,完成该功能,但是我使用过几个插件之后,不知道是不是自己没有找对方法,都没有解决我得问题
我出现得情况是,下拉时请求下一页得数据,但是如果数据条数过多,比如一页请求10条数据,屏幕太短只能显示5条数据,那么再次下拉就不是请求数据,而是想看下面内容~不知道怎么识别是下拉请求数据啊,还是想看下面的数据~
前两天发现自己很傻缺,不使用下拉请求数据,直接到最底部再请求数据就好了啊。。。。然后自己原生写了一个,基本解决了我得问题,只是判断到最底部后请求数据
这两天又研究了一下~出现了下面的代码
代码 myScroll.vue
style样式是自己随便写的,里面注释都有写
<template>
<div class="yo-scroll"
:class="{'down':(state===0),'up':(state==1),refresh:(state===2),touch:touching}"
@touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)">
<section class="inner" :style="{ transform: 'translate3d(0, ' + top + 'px, 0)' }">
<header class="pull-refresh">
<slot name="pull-refresh">
<span class="down-tip">下拉更新...</span>
<span class="up-tip">松开刷新数据...</span>
<span class="refresh-tip">加载中……</span>
</slot>
</header>
<slot>
</slot>
<footer class="load-more">
<slot name="load-more">
<span v-show="downFlag === false">上拉加载更多...</span>
<!-- <span v-if="loadMoreTip">加载中...</span> -->
</slot>
</footer>
<div class="nullData" v-show="dataList.noFlag">暂无更多数据</div>
</section>
</div>
</template>
<script>
export default{
naem:'demo',
props: {
offset: {
type: Number,
default: 100 //默认高度
},
enableInfinite: {
type: Boolean,
default: true
},
enableRefresh: {
type: Boolean,
default: true
},
dataList: {
default: false,
required: false
},
onRefresh: {
type: Function,
default: undefined,
required: false
},
onInfinite: {
type: Function,
default: undefined,
require: false
}
},
data(){
return {
top: 0,
state: 0,
startX: 0, //触摸目标在页面中的x坐标
startY: 0, //触摸目标在页面中的y坐标
touching: false,
infiniteLoading: false,
downFlag: false, //用来显示是否加载
loadMoreTip:false //数据加载中
}
},
methods:{
touchStart(e){ //当手指触摸屏幕时触发
this.startX = e.targetTouches[0].pageX;
this.startY = e.targetTouches[0].pageY;
this.startScroll = this.$el.scrollTop || 0;
this.touching = true;
// this.dataList.noFlag = false; //有更多数据,所以该提示不显示
this.$el.querySelector('.load-more').style.display = 'block'; //上拉加载更多显示
},
touchMove(e){ //当手指在屏幕上滑动的时候连续地触发
if(!this.enableRefresh || this.dataList.noFlag || !this.touching){
return
}
//给下拉做回弹效果
let diff = e.targetTouches[0].pageY - this.startY - this.startScroll ;
if(diff > 0) e.preventDefault()
this.top = Math.pow(diff, 0.8) + (this.state === 2 ? this.offset : 0)
if(this.state === 2) { // in refreshing
return
}
if(this.top >= this.offset) {
this.state = 1
} else {
this.state = 0
}
let more = this.$el.querySelector('.load-more');
if(!this.top && this.state === 0) { //没有到顶部
more.style.display = 'block';
} else {
more.style.display = 'none';
}
},
touchEnd(e){ //当手指从屏幕上离开的时候触发
// if(!this.enableRefresh) {
// return
// }
this.touching = false ;
if(this.state === 2) { // 在刷新中
this.state = 2
this.top = this.offset
return
}
if(this.top >= this.offset) { //刷新
this.refresh()
} else { // 取消刷新
this.state = 0
this.top = 0
}
//用于判断滑动是否在原地
// ---------- 开始 --------------
let endX = e.changedTouches[0].pageX,
endY = e.changedTouches[0].pageY,
dy = this.startY - endY,
dx = endX - this.startX;
//如果滑动距离太短
if(Math.abs(dx) < 2 && Math.abs(dy) < 2) {
console.log("滑动距离太短")
return;
}
// ---------- 结束 --------------
if(!this.enableInfinite || this.infiniteLoading) {
return
}
let outerHeight = this.$el.clientHeight,
innerHeight = this.$el.querySelector('.inner').clientHeight,
scrollTop = this.$el.scrollTop,
ptrHeight = this.onRefresh ? this.$el.querySelector('.pull-refresh').clientHeight : 0,
bottom = innerHeight - outerHeight - scrollTop - ptrHeight;
if(bottom <= this.offset && this.state === 0){
this.downFlag = true;
this.infinite(); //加载
}else{
this.$el.querySelector('.load-more').style.display = 'none';
this.downFlag = false;
}
},
refresh(){
this.state = 2;
this.top = this.offset;
setTimeout(() => {
this.onRefresh(this.refreshDone)
}, 1500);
},
refreshDone(){
this.state = 0
this.top = 0
},
infinite() {
this.state == 2;
this.infiniteLoading = true
setTimeout(() => {
// this.loadMoreTip = true ;
this.onInfinite(this.infiniteDone);
}, 1500);
},
infiniteDone() {
this.infiniteLoading = false
}
}
}
</script>
<style scoped>
.yo-scroll{
font-size: 24px;
position: absolute;
top: 1rem;
left: 0;
bottom:0;
right:0;
overflow: auto;
z-index: 100;
height: auto;
-webkit-overflow-scrolling: touch;
}
.inner{
position: absolute;
/* top:-5rem; */
top:0;
left:0;
width:100%;
height:auto;
transition-duration: 300ms;
}
/* 下拉刷新 */
.pull-refresh{
position: relative;
top:0;
left:0;
width:100%;
height:2rem;
display:flex;
display: -webkit-flex;
justify-content: center;
align-items: center;
}
/* 上拉加载更多 */
.load-more{
width:100%;
height:2rem;
line-height:2rem;
display:flex;
display: -webkit-flex;
align-items: center;
justify-content: center;
text-align:center;
display:none;
}
/* 没有更多数据 */
.nullData{
height:2rem;
line-height:2rem;
text-align:center;
}
.down-tip,.refresh-tip,.up-tip { /*隐藏提示语*/
display: none;
}
.yo-scroll.touch .inner {
transition-duration: 0;
}
.yo-scroll.down .down-tip {
display: block;
}
.yo-scroll.up .up-tip {
display: block;
}
.yo-scroll.refresh .refresh-tip {
display: block;
}
</style>
需要使用上拉加载数据的页面 index.js
<template>
<div id="scrollList">
<div class="contSingleList">
<div class="tabItem">
<slot></slot>
</div>
<v-scroll :on-refresh="onRefresh" :on-infinite="onInfinite" :dataList="scrollData">
<ul class="listItem">
<li v-for="(item,index) in listdata" :key="index">
{{item.time}}
</li>
</ul>
</v-scroll>
</div>
</div>
</template>
<script>
import vScroll from './demo'
export default{
name:'scrollList',
data(){
return{
counter: 1, //当前页
num: 15, // 一页显示多少条
pageStart: 0, // 开始页数
pageEnd: 0, // 结束页数
listdata: [], // 下拉更新数据存放数组
scrollData: {
noFlag: false //暂无更多数据显示
},
}
},
components: {
'v-scroll': vScroll
},
created(){
this.getlist();
},
methods:{
getlist(){
this.$store.dispatch('scroll/getList',this.counter).then(()=>{
console.log(this.counter);
if(this.$store.state.scroll.code == 200){
this.listdata = this.listdata.concat(this.$store.state.scroll.list);
if(this.$store.state.scroll.list.length == 0){
let more = this.$el.querySelector('.load-more')
more.style.display = 'none'; //隐藏加载条
//走完数据调用方法
this.scrollData.noFlag = true;
}
}else{
this.$toast({ message:this.$store.state.scroll.msg });
}
}).catch((e) => {
//alert(e);
});
},
onRefresh(done) {
this.listdata = []
this.counter = 1;
this.getlist();
done()
// this.onInfinite(done)
},
onInfinite(done) {
if(this.scrollData.noFlag){
console.log("111")
}else{
this.counter ++;
this.getlist();
done();
}
}
}
}
</script>
<style scoped>
.listItem{
width:100%;
}
.listItem li{
width:100%;
height:2rem;
border:1px solid red;
box-sizing: border-box;
text-align:center;
}
</style>
js文件请求接口
import axios from 'axios'
export default{
namespaced:true,
state:{
code:0,//状态码
msg:'',//提示信息
list:[],//接收数组
},
mutations:{
mtgetcode(state,data){
state.code = data;
},
mtgetmsg(state,data){
state.msg = data;
},
mtgetlist(state,data){
state.list = data;
},
},
actions:{
getList:function({commit},info){
let token = window.localStorage.getItem('date');
return new Promise((resovle,reject)=>{
axios.get('url?accessToken='+token+'&page='+info).then((res)=>{
const data = res.data;
console.log(data);
commit('mtgetcode',data.code);
commit('mtgetmsg',data.msg);
commit('mtgetlist',data.bill);
resovle(res);
}).catch(error => {
reject(error);
})
})
}
}
}