基于better-scroll封装一个上拉加载下拉刷新组件
1.起因
上拉加载和下拉刷新在移动端项目中是很常见的需求,遂自己便基于better-scroll封装了一个下拉刷新上拉加载组件.
2.过程
better-scroll是目前比较好用的开源滚动库,提供很多灵活的api供我们开发各种实用的组件,文档地址(https://ustbhuangyi.github.io/better-scroll/doc/zh-hans/#better-scroll),本次主要用到它提供的pullDownRefresh 和 pullUpLoad api 开启上拉加载和下拉刷新的功能,同时它还提供两个event用于发送请求,pullingUp会在一次上拉加载之后触发,pullingdown 会在一次下拉刷新之后触发,可以在这两个事件中请求数据.这里有一个坑就是,每次上拉或者下拉之后需要调用finishPullUp或finishPullDown来结束这些动作.另外better-scroll在ios系统上快速滚动可能会出现白屏的bug,而且当你滚动暂停的时候回出现抖动,这些可以通过修改配置项useTransition:false解决,better-scroll会开始以js帧动画来渲染滑动效果,以下是代码部分:
<template>
<div class="scroll" ref="wrapper"> <!-- 数据列表 -->
<div class="list-wrapper">
<slot name="content"></slot>
<!-- 上拉加载 start-->
<slot name="pullup">
<div class="pullup-wrapper" v-if="pullUpLoad">
<div class="before-trigger" v-if="!isPullUpLoad">
{{ pullupText }}
</div>
<div class="after-trigger" v-else>
<loading></loading>
</div>
</div>
</slot>
<!-- 上拉加载 end-->
</div> <!-- 下拉刷新start -->
<slot name="pulldown">
<div class="pulldown-wrapper" :style="pullDownStyle">
<div class="before-trigger" v-if="beforePullDown">
{{ pullDownText }}
</div>
<div class="after-trigger" v-else>
<loading v-if="isPullDown"></loading>
<div v-else>刷新成功</div>
</div>
</div>
</slot>
<!-- 下拉刷新end --> </div>
</template> <script>
import Bscroll from 'better-scroll';
import loading from '../loading/loading.vue';
export default {
componentName : 'scroll',
components:{
loading
},
data(){
return{
scroll : null,
isPullUpLoad : false, // 上拉正在加载中
pullUpDirty : true, // 是否有新数据
isPullDown : false, // 正在刷新
beforePullDown: true, // 未开始下拉刷新
pullDownStyle : {}
}
},
mounted(){
this.initScroll();
},
computed:{
pullupText(){
const moreText = this.pullUpLoad && this.pullUpLoad.more || '上拉加载更多';
const noMoreText = this.pullUpLoad && this.pullUpLoad.nomore || '没有更多数据了';
return this.pullUpDirty && moreText || noMoreText;
},
pullDownText(){
return this.pullDown && this.pullDown.refreshText || '下拉刷新';
}
},
methods:{
forceUpdate(dirty){
if(this.pullUpLoad && this.isPullUpLoad){
this.pullUpDirty = dirty;
this.isPullUpLoad = false;
this.finishPullUp();
this.refresh();
}else if(this.pullDown && this.isPullDown){
this.isPullDown = false;
setTimeout(()=>{ // 让刷新成功停留一段时间
this.finishPullDown();
this.refresh();
},500)
}
},
initScroll(){
if(!this.$refs.wrapper){
return
}
let options = {
probeType : this.probeType,
click : this.click,
startX : this.startX,
startY : this.startY,
tap : this.tap,
pullUpLoad: this.pullUpLoad,
pullDownRefresh: this.pullDown && { threshold: 50,stop : 50 }
} this.scroll = new Bscroll(this.$refs.wrapper, options); // 代理scrollEnd事件
if(this.scrollEnd){
this.scroll.on('scrollEnd',(pos)=>{
this.$emit('scrollEnd', pos)
})
}
// 代理scroll事件
if(this.onScroll){
this.scroll.on('scroll',(pos)=>{
console.log(pos.y);
let position = pos.y-50 >= 20 && 20 || pos.y-50;
this.$set(this.pullDownStyle, 'top', position + 'px')
this.$emit('scroll', pos);
})
}
// 代理pullingUp事件,在一次上拉加载的动作后.
if(this.pullUpLoad){
this.onPullingUp();
} // 代理pullingDown事件,在一次下拉刷新的动作后.
if(this.pullUpLoad){
this.onPullingDown();
}
},
onPullingUp(){
this.scroll.on('pullingUp',()=>{
this.isPullUpLoad = true;
this.$emit('pullingUp');
})
},
onPullingDown(){
this.scroll.on('pullingDown', ()=>{
this.beforePullDown = false;
this.isPullDown = true;
this.$emit('pullingDown');
})
},
refresh(){
this.scroll && this.scroll.refresh();
},
finishPullUp(){
this.scroll && this.scroll.finishPullUp();
},
finishPullDown(){
this.scroll && this.scroll.finishPullDown();
}
},
watch:{
list(){
// 列表有变化刷新,没有变化在父组件调用forceUpdate
this.forceUpdate(true);
},
pullDownStyle:{
handler(val){
if(val.top == '-50px'){
this.beforePullDown = true;
}
},
deep : true
}
},
props : {
list : { // 数据源
type : Array,
default(){
return []
}
},
startX : { // 横轴方向初始化位置
type : Number,
default : 0
},
startY : { // 纵轴方向初始化位置
type : Number,
default : 0
},
probeType : { // 实时派发滚动位置的等级
type : Number,
default : 3
},
click : { // 开启better-scroll派发的click事件
type : Boolean,
default : true,
},
tap : {
type : Boolean, // 开启better-scroll派发的tap事件
default : false
},
scrollEnd : { // 监听滚动到结束位置
type : Boolean,
default : false
},
pullDown : { // 是否开启下拉刷新
type : null,
default : false
},
pullUpLoad : { // 是否开启上拉加载
type : null,
default : false
},
onScroll : { // 监听滚动事件
type : Boolean,
default : true
}
} }
</script> <style scoped lang="scss">
.scroll{
width: 100%;
height: 100%;
overflow: scroll;
position: relative; }
.list-wrapper{
width: 100%;
min-height: 101%;
}
.pulldown-wrapper{
width: 100%;
height: 50px;
position: absolute;
display: flex;
align-items : center;
justify-content : center;
left: 0;
top: -50px;
z-index: 100;
}
.pullup-wrapper{
width: 100%;
height: 50px;
display: flex;
align-items : center;
justify-content : center;
}
</style>
基于better-scroll封装一个上拉加载下拉刷新组件的更多相关文章
- mui scroll和上拉加载/下拉刷新
mui中 scroll和上拉加载/下拉刷新同时存在会出现两个滚动条 把/* */ /* //mui页面鼠标拖动代码: mui('.mui-scroll-wrapper').scroll({ dec ...
- Vue mint ui用在消息页面上拉加载下拉刷新loadmore 标记
之前总结过一个页面存在多个下拉加载的处理方式,今天再来说一下在消息页面的上拉加载和下拉刷新,基本上每个app都会有消息页面,会遇到这个需求 需求:每次加载十条数据,上拉加载下拉刷新,并且没有点击查看过 ...
- 上拉加载下拉刷新控件WaterRefreshLoadMoreView
上拉加载下拉刷新控件WaterRefreshLoadMoreView 效果: 源码: // // SRSlimeView // @author SR // Modified by JunHan on ...
- APICloud上啦加载下拉刷新模块
apicloud有自带的上啦加载下拉刷新,当让也可以用第三方或者在模块库里面找一个使用 一.下拉刷新,一下代码写在 apiready = function (){} 里面 apiready = fun ...
- RecyclerView 上拉加载下拉刷新
RecyclerView 上拉加载下拉刷新 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/teach_s ...
- 微信小程序上拉加载下拉刷新
微信小程序实现上拉加载下拉刷新 使用小程序默认提供方法. (1). 在xxx.json 中开启下拉刷新,需要设置backgroundColor,或者是backgroundTextStyle ,因为加载 ...
- Flutter上拉加载下拉刷新---flutter_easyrefresh
前言 Flutter默认不支持上拉加载,下拉刷新也仅仅支持Material的一种样式.Android开发使用过SmartRefreshLayout的小伙伴都知道这是一个强大的刷新UI库,集成了很多出色 ...
- React-Native 上拉加载下拉刷新
react-native 上下拉加载的控件效果都不好,找了半天没找到,正打算自已封装的时候,无意中找到了一个比较好的控件,大家看一下: react-native-refresh-list-view 这 ...
- js上拉加载下拉刷新
写在前边: 工作需要,使用ajax在原来的列表下边使用ajax请求后台数据,拼接在列表最下边,在github转了好久,发现了一个bug极多的js刷新插件,尝试了一个下午,就在快放弃的时候,发现下边有留 ...
随机推荐
- Python数据分析2------数据探索
一.数据探索 数据探索的目的:及早发现数据的一些简单规律或特征 数据清洗的目的:留下可靠数据,避免脏数据的干扰. 两者没有严格的先后顺序,经常在一个阶段进行. 分为: (1)数据质量分析(跟数据清洗密 ...
- Project Euler 14 Longest Collatz sequence
题意:对于任意一个数 N ,寻找在 100,0000 之内按照规则( N 为奇数 N = N * 3 + 1 ,N 为偶数 N = N / 2 ,直到 N = 1 时的步数 )步数的最大值 思路:记忆 ...
- UVALive-8138 Number Generator 概率dp+优化
题目链接:https://cn.vjudge.net/problem/UVALive-8138 题意 有一个随机数生成器,输出1-n的整数. 现在已经输出了k个数,问再取几个数才能使取出的所有数的个数 ...
- [洛谷 P2365] 任务安排 (线性dp)
3月14日第二题!! 题目描述 N个任务排成一个序列在一台机器上等待完成(顺序不得改变),这N个任务被分成若干批,每批包含相邻的若干任务.从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间 ...
- P1892 团伙
题目描述 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么是敌人.而且有一点是肯定的,就是: 我朋友的朋友是我的朋友: 我敌人的敌人也是我的朋友. 两个强盗是同一团伙的 ...
- [SPOJ1716] GSS3 - Can you answer these queries III
线段树操作. 维护一个区间最大连续子段和,左最大连续子段和,右最大连续子段和即可. 最后不知道怎么搞,query的时候返回了个结构体. #include <cstdio> #include ...
- https自签证书
linux自带openssl,所以最好在linux平台操作 第一步:生成采用des3算法保护的私钥:openssl genrsa -des3 -out private-rsa.key 1024 命令执 ...
- redi通过哨兵sentinel实现主从切换
本次实验主要为了让哨兵监听redis主从复制,当主节点关闭后,哨兵会选举一台从节点成为主节点,并且让其他从节点变成新主节点得从节点 本次理论需要三台机器,一主两从,为了方便用一台服务器开启三个实例,一 ...
- 01.Python基础-5.函数
1 函数的介绍 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 内置函数 自定义函数 2 函数的定义和调用 2.1 函数的定义和调用 定义 def 函数名([参数]): 代码块 [ ...
- 监控Oracle计数器