likes
comments
collection
share

微信小程序 自定义刷新实现

作者站长头像
站长
· 阅读数 14

关于为什么会使用 自定义刷新?

  • 自定义头部导航栏下拉刷新不会固定 ( 安卓异常 ios正常 ).
  • 下拉刷新三个点的位置 是根据自定义头部来的 用户需要下拉较长距离 才能看到三个点.
  • UI 样式问题.

效果图

微信小程序 自定义刷新实现

微信小程序 自定义刷新实现

最终效果跟下方是一样的上面没动图......

微信小程序 自定义刷新实现

思路分析

  • 在页面顶部放置一个view,这个view主要用来展示刷新状态提示用户,view初始高度为0
  • 监听用户手指touch事件,根据用户移动的距离来动态改变顶部刷新状态view的高度
  • 设置一个高度阈值,当下拉距离大于等于这个阈值,松开手指触发刷新操作

组件实现

微信小程序 自定义刷新实现

index.wxml

<!-- wxml布局文件 -->
<scroll-view style='height:100%' scroll-y='{{!isindrag}}' bindscroll='scorll'>
    <!-- 监听布局touch事件    touchstart 手指触摸动作开始
                             touchend	手指触摸动作结束
                             touchmove	手指触摸后移动 -->
    <view class='column' bindtouchstart='start' bindtouchend='end' bindtouchmove='move'>
        <!-- //刷新状态view -->
        <view style='height:{{viewHeight}}px;margin-top: {{marginTop}}px;padding-top: {{paddingTop}}px;' class='refresh'>
            <image wx:if="{{!RefreshStatus&&isindrag}}" class="sunshine" src="../../assets/taiyang.png"></image>
            <image wx:if="{{!RefreshStatus&&isindrag}}" class="cloud" src="../../assets/yun.png"></image>
            <view wx:if="{{RefreshStatus}}" class="sunshineText"> {{desc}}</view>
        </view>
        <slot></slot>
    </view>
</scroll-view>
paddingTop 参数

有的页面多了个Tab 标签页所以要加上这个高度 否则标签会覆盖 展示位置会有问题

微信小程序 自定义刷新实现

index.js

var sy; //记录手指的y坐标
Component({
      properties: {
        // 自定义文案
        text: {
            type: String,
            value: '记录已更新'
        },
       // 滚动条距离顶部的距离  用户如果上拉滚动底部后,在下拉往上的时候,会一直派发父组件的事件.
        // 这个参数的用处就在于滚动条的高度如果大于100 下拉就不让他派发事件调用接口了.
        // 其实本身咱们用的 scroll-view  bindscroll='scorll'事件.
        // 是可以拿到滚动条位置的.但是必须有固定高度... 然后才有这个参数. 
        // 通过父组件的page页 调用onPageScroll事件时时传送当前滚动条的位置.(下方有例子 )
        TopVal: {
            type: [String, Number],
            value: 0
        },
        //上方 有关于这个参数的图例
        paddingTop:{
            type: [String, Number],
            value: 0
        }
    },

    data: {
        desc: '', //刷新提示语
        // desc: '下拉刷新', //刷新提示语
        viewHeight: 0, //刷新view高度阈值
        scrolltop: 0, //scorll-view滑动离顶部的距离
        isindrag: false, //是否在下拉状态(必须要滑动到顶部才能触发)
        RefreshStatus: false //是否刷新完成
    },
    methods: {
        start(e) {
            //记录手指触摸是的y坐标
            console.log(e);
            sy = e.touches[0].clientY;
            console.log('开始触摸 sy : ' + sy + ' scrolltop : ' + this.data.scrolltop)
        },
        move(e) {
            //计算手指滑动的距离
            var delta = e.touches[0].clientY - sy;
            console.log('delta : ' + delta)
            //scorll-view滑动到顶部且继续向上滑动时,走scorll-view滑动流程
            if (this.data.viewHeight <= 0 && delta <= 0) {
                return;
            }
            //scorll-view已经滑动到顶部,继续下拉进入下拉状态
            if (this.data.scrolltop <= 0) {
                if (this.data.isindrag == false) {
                    this.setData({
                        isindrag: true
                    })
                }
                var tempdelta = 0;
                console.log('viewHeight : ' + this.data.viewHeight)
                if (delta > 0) { //手指向下滑动
                    if (this.data.viewHeight > 70) { //触发阈值,更改状态
                        // this.setData({
                        //     desc: '松开刷新'
                        // })
                        tempdelta = this.data.viewHeight + delta / (this.data.viewHeight - 70) //增大下拉阻尼感
                    } else {
                        // this.setData({
                        //     desc: '下拉刷新'
                        // })
                        //手指移动未到阈值,按正常滑动增加高度
                        tempdelta = this.data.viewHeight + delta
                    }
                } else { //手指向上滑动
                    tempdelta = this.data.viewHeight + delta
                    //刷新状态view最小为0
                    if (tempdelta <= 0) {
                        tempdelta = 0;
                    }
                    // this.setData({
                    //     desc: '下拉刷新'
                    // })
                }
                //滑动完成设置刷新view高度
                if (!this.data.RefreshStatus) {
                    this.setData({
                        // viewHeight: tempdelta
                    })
                }

            }
            //每次滑动事件后记录y坐标
            sy = e.touches[0].clientY;
        },
        end(e) {
            console.log('手指离开')
            var that = this;
            console.log(this.data.TopVal);
            //手指离开时,如果阈值大于等于70,则触发刷新
            if (this.data.viewHeight >= 70 & this.data.TopVal < 100) {
                that.setData({
                    // desc: '正在刷新...',
                    viewHeight: 70,
                })
                //模拟耗时操作,2秒后恢复正常状态
                // setTimeout(function () {
                //     sy = 0
                //     that.setData({
                //       desc: '下拉刷新',
                //       hei: 0,
                //       isindrag: false,
                //       scrolltop: 0
                //     })
                //   }, 2000)

                //离开后触发 父组件相应接口事件
                this.triggerEvent('endEvent');
            } else {
                //未下拉到阈值,松开时则收起刷新view
                sy = 0;
                that.setData({
                    // desc: '下拉刷新',
                    viewHeight: 0,
                    isindrag: false,
                    scrolltop: 0,
                    RefreshStatus:false
                })
            }
        },
        //父组件触发事件  (显示文案后,2秒后再次调用下面 FiveMillisecondsLater 方法 彻底关闭)
        closeGold() {
            sy = 0;
            this.setData({
                // desc: '记录已更新',
                desc: this.data.text,
                RefreshStatus: true,
                viewHeight: 32,
            })
        },
        FiveMillisecondsLater() {
            this.setData({
                // desc: '下拉刷新',
                viewHeight: 0,
                isindrag: false,
                scrolltop: 0,
                RefreshStatus: false
            })
        },
        //这个事件未触发 原因:没有固定高度! 上方有其他获取滚动条的方案。如果有固定高度可以不用TopVal参数!!!!!!
        scorll(e) {
            //未进入下拉状态时,记录scorll-view滑动距离顶部的距离
            var st = e.detail.scrollTop;
            console.log('滚动 st : ' + st)
            if (this.data.isindrag == false) {
                this.setData({
                    scrolltop: st
                })
            }
        },
    }
})

index.json

{
    "component": true
}

index.wxss

.refresh {
    background: #F7F7F7;
    position: relative;
}

.sunshine {
    width: 76rpx;
    height: 76rpx;
    position: absolute;
    z-index: 2;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
}

.cloud {
    width: 242rpx;
    height: 56rpx;
    position: absolute;
    z-index: 1;
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
}

.sunshineText {
    text-align: center;
    height: 64rpx;
    line-height: 64rpx;
    background: #E3F8EE;
    font-size: 28rpx;
    font-family: 'PingFang SC-Regular, PingFang SC';
    font-weight: 400;
    color: #28C87A;
}

组件使用

endEvent 子组件抛出的事件

使用时 需要把小程序默认的刷新事件关闭 ( "enablePullDownRefresh": false )

app.json "usingComponents" 对象引入组件

<scrollReflash bindendEvent="endEvent" TopVal="{{TopVal}}" text="记录已更新" id="scrollReflash" 
paddingTop='55'>
        <view>
             我是测试列表
             我是测试列表
             我是测试列表
             我是测试列表
        </view>
</scrollReflash>
    
    
    //方法调用
     endEvent() {
        this.getDetailById(true)
     },
    //小程序获取滚动条高度
     onPageScroll: function (e) {
            this.setData({
                TopVal: e.scrollTop,
            })
     },
    //派发事件调用下拉刷新接口
     getDetailById(show) {
            let countDown = this.selectComponent('#scrollReflash'); // 页面获取自定义组件实例
            if (show) {
                countDown.closeGold(); // 通过实例调用组件事件
            }
            setTimeout(() => {
                countDown.FiveMillisecondsLater(); // 通过实例调用组件事件
            }, 2000);
     },
]()

遇到的问题

微信小程序 自定义刷新实现 暂时也没有好的方案. 所以只能父传给子组件 .

亲测可用 有问题滴滴🙂