1.下拉刷新和上拉加载更多组件

Scroller.vue

<!-- 下拉刷新 上拉加载更多 组件 -->
<template>
<div
:style="marginTop"
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-show="downFlag === true">加载中……</span>
</slot>
</footer>
<!-- 暂无数据提示语 -->
<div class="nullData" v-show="dataList.noFlag">暂无更多数据</div>
</section>
</div>
</template> <script>
export default {
// 接收父组件参数
props: {
marginTop: {
default: "margin-top:40px;"
},
// 默认高度
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, // 状态: 0 下拉/ 1 上拉 / 2 刷新
startX: 0, // 手指滑动起始位置 X轴
startY: 0, // 手指滑动起始位置 Y轴
touching: false, // -webkit-overflow-scrolling
infiniteLoading: false, // 加载更多效果
downFlag: false, //用来显示是否加载中
}
},
methods: {
// 手指刚开始滑动
touchStart(e) {
this.startY = e.targetTouches[0].pageY;
this.startX = e.targetTouches[0].pageX;
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) { // 刷新中
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
}
//用于判断滑动是否在原地 ----begin
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;
}
//--------end--------
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)
}, 300);
},
// 结束刷新
refreshDone() {
this.state = 0
this.top = 0
},
// 加载更多
infinite() {
this.infiniteLoading = true
setTimeout(() => {
this.onInfinite(this.infiniteDone);
}, 2000);
},
// 结束加载更多
infiniteDone() {
this.infiniteLoading = false
}
}
}
</script> <style lang="less" scoped>
.yo-scroll {
// margin-top: 40px; // 解决有标题栏的bug
font-size: 16px;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
z-index: 100;
height: auto;
-webkit-overflow-scrolling: touch;
.inner {
position: absolute;
top: -50px;
width: 100%;
height: auto;
transition-duration: 300ms;
.pull-refresh {
position: relative;
left: 0;
top: 0;
width: 100%;
height: 50px;
display: flex;
display: -webkit-flex;
align-items: center;
justify-content: center;
}
.load-more {
height: 50px;
line-height: 50px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
display: none;
}
.nullData { //暂无更多数据样式
font-size: 16px;
color: #999999;
height: 50px;
line-height: 60px;
text-align: center;
}
.down-tip,
.refresh-tip,
.up-tip {
display: none;
}
.up-tip:before,
.refresh-tip:before {
content: '';
display: inline-block;
width: 110px;
height: 40px;
font-size: 16px;
background-size: 70% !important;
position: absolute;
top: 0;
left: 20%;
}
.up-tip:before {
background: url(../assets/images/down-logo.png) no-repeat left;
}
.refresh-tip:before {
background: url(../assets/images/refresh-logo.gif) no-repeat left;
}
}
} .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>

2.页面调用

LoadMore.vue

<!-- 加载更多 -->
<template>
<div>
<!-- 标题栏 -->
<mt-header title="加载更多">
<router-link to="/" slot="left">
<mt-button icon="back">返回</mt-button>
</router-link>
</mt-header>
<!-- 列表 -->
<div class="cont">
<m-scroller :on-refresh="onRefresh" :on-infinite="onInfinite" :dataList="scrollData" :marginTop="marginTop">
<ul>
<li v-for="(item,index) in listdata">{{item.name}}</li>
</ul>
</m-scroller>
</div>
</div>
</template> <script>
import mScroller from '../components/Scroller' export default {
components: {
mScroller
},
data() {
return {
marginTop:'margin-top:40px;',
pageStart: 0, // 开始页数
pageEnd: 0, // 结束页数
listdata: [], // 数据列表
scrollData:{
noFlag: false //暂无更多数据显示
}
}
},
mounted: function() {
// 首次请求数据
this.fetchData();
},
methods: {
fetchData() {
this.axios.get('/api/testData').then((response) => {
this.listdata = response.data.data.list;
// 获取总页数
this.pageEnd = response.data.data.totalPage;
// 还原
this.pageStart = 0;
})
},
// 下拉刷新
onRefresh(done) {
this.fetchData();
done(); // call done
},
// 上拉加载更多
onInfinite(done) {
this.pageStart++;
// 加载条
let more = this.$el.querySelector('.load-more');
// 判断是否显示加载条
if(this.pageStart > this.pageEnd){
//走完数据调用方法
this.scrollData.noFlag = true;
}else{
let _this = this;
this.axios.get('/api/testData').then((response) => {
_this.listdata = _this.listdata.concat(response.data.data.list);
// 获取总页数
_this.pageEnd = response.data.data.totalPage;
})
}
// 隐藏加载条
more.style.display = 'none';
done();
}
}
}
</script> <style lang="less" scoped>
ul {
li {
min-height: 50px;
line-height: 50px;
text-align: center;
border: 1px solid red;
}
}
// 隐藏滚动条
::-webkit-scrollbar{
display:none;
}
</style>

3.效果图

vue2.0 自定义 下拉刷新和上拉加载更多(Scroller) 组件的更多相关文章

  1. juery下拉刷新,div加载更多元素并添加点击事件(二)

    buffer.append("<div class='col-xs-3 "+companyId+"' style='padding-left: 10px; padd ...

  2. android--------自定义控件ListView实现下拉刷新和上拉加载

    开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,为了方便重写的ListView来实现下拉刷新,同时添加了上拉自动加载更多的功能. Android下拉刷新可以分为两种情况: 1.获取 ...

  3. Android 自定义 ListView 上下拉动“刷新最新”和“加载更多”歌曲列表

    本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码 ...

  4. 下拉刷新和上拉加载 Swift

    转载自:http://iyiming.me/blog/2015/07/05/custom-refresh-and-loading/ 关于下拉刷新和上拉加载,项目中一直使用MJRefresh(原先还用过 ...

  5. Diycode开源项目 搭建可以具有下拉刷新和上拉加载的Fragment

    1.效果预览 1.1.这个首页就是一个Fragment碎片,本文讲述的就是这个碎片的搭建方式. 下拉会有一个旋转的刷新圈,上拉会刷新数据. 1.2.整体结构 首先底层的是BaseFragment 然后 ...

  6. Android实现RecyclerView的下拉刷新和上拉载入很多其它

    需求 先上效果图, Material Design风格的下拉刷新和上拉载入很多其它. 源代码地址(欢迎star) https://github.com/studychen/SeeNewsV2 假设对于 ...

  7. RecyclerView下拉刷新和上拉加载更多实现

    RecyclerView下拉刷新和上拉加载更多实现 转 https://www.jianshu.com/p/4ea7c2d95ecf   在Android开发中,RecyclerView算是使用频率非 ...

  8. Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

    RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...

  9. iscroll.js 下拉刷新和上拉加载

    html代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

随机推荐

  1. 21 段实用便捷的 PHP 代码

    PHP 是目前使用最广泛的基于 Web 的编程语言,驱动着数以百万计的网站,其中也包括如 Facebook 等一些大型站点.这里收集了 21 段实用便捷的 PHP 代码摘录,对每种类型的 PHP 开发 ...

  2. LiveScript 操作符

    The LiveScript Book     The LiveScript Book 操作符 数字 标准的数学操作符: 1.1 + 2 # => 32.3 - 4 # => -13.6 ...

  3. pycharm配置 自动运行指定脚本

    配置:RUN -Debug Configuration Script: 脚本的地址 Script Parameters: 脚本的参数 Interpreter: python解释器

  4. struts2和spring的两种整合方式

    首先,来看看如何让Spring 来管理Action. 在struts.xml中加入 <constant name="struts.objectFactory" value=& ...

  5. EF知识和经验

    AsNoTracking提高查询性能 AsNoTracking的作用就是在查询的时候不做追踪,这样会查询的更快,但是这样做会有一个缺陷(不能对查询的数据做修改操作). var student2 = d ...

  6. 【Go】Panic函数

    panic(运行时恐慌)是一种只会在程序运行时才回抛出来的异常.在panic被抛出之后,如果没有在程序里添加任何保护措施的话,程序就会在打印出panic的详情,终止运行. 如果一个panic是无意间引 ...

  7. 项目记事【Hibernate-1】:调用 saveOrUpdate() 方法出错

    Hibernate 版本:3.3.1 背景: 后端编辑一个对象,该对象(ProductDO)下,有一个另一个自定义对象(ProductLiabilityDO)的 OneToMany 关系,如下: @O ...

  8. 【bzoj3698】XWW的难题 有上下界最大流

    题目描述 XWW是个影响力很大的人,他有很多的追随者.这些追随者都想要加入XWW教成为XWW的教徒.但是这并不容易,需要通过XWW的考核.XWW给你出了这么一个难题:XWW给你一个N*N的正实数矩阵A ...

  9. [APIO2015] 雅加达的摩天楼 (分块,最短路)

    题目链接 Solution 分块+\(Dijkstra\). 难点在于建边,很明显 \(O(n^2)\) 建边会挂一堆 . 那么考虑一下, \(n^2\) 建边多余的是哪些东西 \(???\) 很显然 ...

  10. bzoj 1069 凸包+旋转卡壳

    题目大意 在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成 的多边形面积最大. 分析 枚举对角线的一个端点 另一个端点开始转 转的时候求出对角线左边面积 ...