uniapp APP下使用list组件的下拉刷新和触底加载

疯狂紫萧 2020-06-03

uni-app App端内置了一个基于 weex 改进的原生渲染引擎,提供了原生渲染能力。

在App端,如果使用vue页面,则使用webview渲染;如果使用nvue页面(native vue的缩写),则使用原生渲染。

list是app端nvue专用组件,详细介绍在官网https://uniapp.dcloud.io/component/list?id=list

1、下拉刷新和触底加载

<refresh> 组件为容器提供下拉刷新功能,

<refresh> 提供两个事件=》

pullingdown:被下拉时触发;refresh :被下拉完成时触发(理解为touchend 时)

<list>提供一个事件,和一个属性设定触底加载的距离

loadmore:列表滚动到底部将会立即触发这个事件,你可以在这个事件的处理函数中加载下一页的列表项。 如果未触发,请检查是否设置了loadmoreoffset的值,建议此值设置大于0;

loadmoreoffset:触发 loadmore 事件所需要的垂直偏移距离(设备屏幕底部与 list 底部之间的距离);

 uniapp APP下使用list组件的下拉刷新和触底加载 

<template>
    <view class="list">
        <!-- list组件必须显示的指定宽高,或者使用定位方式 -->
        <list class="list" loadmoreoffset="10" @loadmore="loadMore" ref="list">
            <refresh 
                :display="refreshing ? ‘show‘ : ‘hide‘" 
                @refresh="onrefresh" 
                @pullingdown="onpullingdown"
                @click="reFresh">
                <view class="loading-more">
                    <loading-indicator style="margin-right:15px;"></loading-indicator>
                    <text class="loading-more-text">{{refreshText}}</text>
                </view>
            </refresh>
            <cell v-for="(item,index) in list" 
                    :key="index" 
                    :ref="‘cell‘+index">
                    <view class="cell">
                        <text>{{item}}</text>
                    </view>
            </cell>
            <cell v-if="list.length>8 && !noData">
                <view class="loading-more">
                    <loading-indicator style="margin-right:15px;"></loading-indicator>
                    <text class="loading-more-text">加载中...</text>
                </view>
            </cell>
            <cell v-if="noData">
                <view class="loading-more">
                    <text class="loading-more-text">没有更多数据了</text>
                </view>
            </cell>
        </list>
        <view class="top" style="bottom: 150px;" @click="reLoad">
            <text>刷新</text>
        </view>
        <view class="top"  @click="clickTop()">
            <view style="background-color: pink;" @click.stop="toTop(1,$event)">
                <text>toTop</text>
            </view>    
        </view>
    </view>
    
</template>

<script>
    //只在nvue 页面有该模块
    const dom = weex.requireModule(‘dom‘)
    export default {
        data() {
            return {
                list: [1, 2, 3, 4, 5, 6,7,8],
                noData:false,
                refreshText:‘‘,
                loading:false,
                refreshing:false
            }
        },
        methods: {
            //开始下拉时
            onpullingdown(e){
                //当正在刷新的时候直接返回
                if(this.refreshing){
                    return;
                }
                if (Math.abs(e.pullingDistance) > Math.abs(e.viewHeight)) {
                    //当下拉的距离大于fresh组件的高度
                    this.refreshText = "释放立即刷新";
                } else {
                    this.refreshText = "下拉可以刷新";
                }
            },
            onrefresh(){
                if(this.loading){
                    //当正在调用接口获取数据时,此时的下拉不做任何操作
                    return;
                }
                this.refreshText="正在刷新...";
                //刷新数据
                //模拟接口延迟
                this.loading = true;
                this.refreshing = true;
                //刷新成功
                setTimeout(()=>{
                    this.list = [1,2,3,4,5,6,7,8];
                    this.loading = false;
                    this.refreshing = false;
                    this.loadErr = false;
                },300);
                //模拟刷新失败
                // setTimeout(()=>{
                //     this.loading = false;
                //     this.refreshText = ‘刷新失败,点击重试‘;
                //     this.loadErr = true;
                // },300);
                
            },
            reFresh(){
                if(!this.loadErr){
                    return;
                }
                this.refreshText="正在刷新...";
                setTimeout(()=>{
                    this.list = [1,2,3,4,5,6,7,8];
                    this.loading = false;
                    this.refreshing = false;
                    this.loadErr = false;
                },300);
            },
            loadMore(){
                let data = [];
                let v = this.list[this.list.length-1];
                if(v==200){
                    this.noData = true;
                    return;
                }
                for(let i = 0;i<4;i++){
                    v++;
                    data.push(v);
                }
                //模拟接口返回时间延迟
                setTimeout(()=>{
                    this.list = this.list.concat(data);
                },300);
                
            },
            reLoad(){
                //当屏幕已经向下滚动,此时刷新,如果数据超过一屏,此时滚动条不会自动置顶
                this.list = [1,2,3,4,5,7,8,9];
                this.scrollElement(0);
            },
            toTop(params,e){
                //nvue下阻止事件冒泡的方法
                e.stopPropagation()
                this.scrollElement(0);
            },
            //滚动到某一个元素
            scrollElement(index){
                if (this.$refs[‘cell‘+index]) {
                    //滑动到顶部
                    let el = this.$refs[‘cell‘+index][0];
                    dom && dom.scrollToElement(el, {
                        // animated:false //滚动的动画,默认有
                    });
                }
            },
            clickTop(e){    
                uni.showToast({
                    title:‘事件冒泡了‘
                })
            }
        }
    }
</script>

<style>
    .list{
        position: absolute;
        top:0;
        bottom: 0;
        left:0;
        right: 0;
        /* #ifndef APP-PLUS */
        display: flex;
        flex-direction: column;
        /* #endif */
    }
    .cell {
        padding-left: 20px;
        padding-top: 40px;
        padding-right: 20px;
        padding-bottom: 40px;
        background-color: #F9D7EA;
        margin-top: 15px;
    }
    .loading-more {
        align-items: center;
        justify-content: center;
        padding-top: 14px;
        padding-bottom: 14px;
        text-align: center;
        flex-direction: row;
        width:750rpx;
    }
    .loading-more-text {
        font-size: 28upx;
        color: #999;
    }
    .top{
        position: fixed;
        right:5px;
        background-color: #FFFFFF;
        bottom:50px;
        width:80px;
        height: 80px;
        border-radius: 50%;
        box-shadow: 0 1px 20px 0 rgba(195, 195, 195, 0.5);
        align-items: center;
        justify-content: center;
    }
    
</style>

注:如果上拉加载数据后,再下拉刷新,然后无法再触发loadmore事件时,请重置loadmore

loadMore(e) {
      //loadmore 事件中重置
    this.$refs["list"].resetLoadmore();
}

相关推荐