DCloud-MUI 下拉刷新与加载更多

下拉刷新

单WebView

实现原理

下拉刷新,触发的是原生下拉刷新控件,而整个webview位置不会发生变化,所以不会在拖动过程中发生DOM重绘,当控件拖动到一定位置触发动态加载数据以及刷新操作。此模式下拉刷新,相比双webview 模式,不创建额外 webview,性能更优。

单webview下拉刷新组件使用

优点:

性能更优,体现在两点:

相比双webview,不创建额外子 webview 性能消耗更少

下拉拖动过程中不会发生重绘,也减少了性能消耗

缺点:

仅支持‘cricle’样式以及该样式的颜色自定义

使用示例

S1.DOM中加入MUI下拉刷新布局组件

<!--下拉刷新容器-->

<div id="pullrefresh" class="mui-content mui-scroll-wrapper">

     <div class="mui-scroll">

         <!--数据列表-->

         <ul class="mui-table-view mui-table-view-chevron"></ul>

     </div>

</div>

S2.JS代码中进行初始化配置

mui.init({

  pullRefresh : {

    container:"#refreshContainer",//下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等

    down : {

      style:'circle',//必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式

      color:'#2BD009', //可选,默认“#2BD009” 下拉刷新控件颜色

      height:'50px',//可选,默认50px.下拉刷新控件的高度,

      range:'100px', //可选 默认100px,控件可下拉拖拽的范围

      offset:'0px', //可选 默认0px,下拉刷新控件的起始位置

      auto: true,//可选,默认false.首次加载自动上拉刷新一次

      callback :pullfresh-function //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;

    }

  }

});

 

下拉刷新主要API

N1.启用与禁用下拉刷新-官方已删除描述

    单/双WebView模式使用方法类似,可以通过代码动态设置下拉刷新的启用与禁用。禁用下拉刷新后,下拉容器不会再对下拉手势作出相应,并且不会有下拉回弹效果。

// 禁用

mui('#refreshContainer').pullRefresh().disablePulldownToRefresh();

//启用

mui('#refreshContainer').pullRefresh().enablePulldownToRefresh();

 

N2.下拉刷新结束

    单/双WebView模式使用方法类似,可以通过代码动态设置下拉刷新的启用与禁用。禁用下拉刷新后,下拉容器不会再对下拉手势作出相应,并且不会有下拉回弹效果。

mui('#pullrefresh').pullRefresh().endPulldownToRefresh();

 

 

 

双WebView

实现原理

webview 模式的下拉刷新,创建一个子 webview 添加列表;拖动时,拖动的是一个完整的 webview,避免了类似 DIV 拖动流畅度不好的问题,回弹动画使用原生动画。

模式说明:

优点:

可自定义下拉刷新样式,更改文字等等.参考关于自定义下拉刷新样式问答

缺点:

相比单 webview,性能消耗更大,不过都比 div 模式的要好用

DOM结构需要统一配置

双WebView模式使用

    双WebView模式与单WebView模式使用差别主要在配置参数的不同。

双WebView模式配置参数:

mui.init({

  pullRefresh : {

    container:"#refreshContainer",//下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等

    down : {

      height:50,//可选,默认50.触发下拉刷新拖动距离,

      auto: true,//可选,默认false.首次加载自动下拉刷新一次

      contentdown : "下拉可以刷新",//可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容

      contentover : "释放立即刷新",//可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容

      contentrefresh : "正在刷新...",//可选,正在刷新状态时,下拉刷新控件上显示的标题内容

      callback :pullfresh-function //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;

    }

  }

});

 

参考:

    http://dev.dcloud.net.cn/mui/pulldown/

 

 

 

上拉加载

实现功能

页面滚动到底,显示“正在加载...”提示(mui框架提供)

执行加载业务数据逻辑(开发者提供)

加载完毕,隐藏"正在加载"提示(mui框架提供)

使用示例

S1.DOM中加入MUI下拉刷新布局组件

<!--下拉刷新容器-->

<div id="pullrefresh" class="mui-content mui-scroll-wrapper">

     <div class="mui-scroll">

         <!--数据列表-->

         <ul class="mui-table-view mui-table-view-chevron"></ul>

     </div>

</div>

S2.JS代码中进行初始化配置

mui.init({

  pullRefresh : {

    container:refreshContainer,//待刷新区域标识,querySelector能定位的css选择器均可,比如:id、.class等

    up : {

      height:50,//可选.默认50.触发上拉加载拖动距离

      auto:true,//可选,默认false.自动上拉加载一次

      contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容

      contentnomore:'没有更多数据了',//可选,请求完毕若没有更多数据时显示的提醒内容;

      callback :pullfresh-function //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;

    }

  }

});

 

下拉刷新主要API

N1. 结束上拉加载

    加载完新数据后,需要执行endPullupToRefresh()方法,结束转雪花进度条的“正在加载...”。

// endMore

// true 没有更多了

// false 显示更多

mui('#pullrefresh').pullRefresh().endPullupToRefresh(endMore);

// 重置上拉加载

// 调用endPullupToRefresh(true)后需要重新启用加载更多需要重载上拉加载

mui('#pullrefresh').pullRefresh().refresh(true);

 

N2.禁用/启用上拉加载

    在部分场景下希望禁用上拉加载,比如在列表数据过少时,不想显示“上拉显示更多”、“没有更多数据”的提示语,开发者可以通过调用disablePullupToRefresh()方法实现类似需求。

// 禁用

mui('#pullrefresh'').pullRefresh().disablePullupToRefresh();

// 启用

mui('#pullrefresh'').pullRefresh().enablePullupToRefresh();

N3.自动上拉加载

    调用后触发上拉加载更多。

// Timeout延时必须

setTimeout(function() {

     mui('#pullrefresh').pullRefresh().pullupLoading();

},50);

 单WebView完整示例

<!DOCTYPE html>
<html style="background: white;">

    <head>
        <meta charset="utf-8">
        <title>Hello MUI</title>
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">

        <link rel="stylesheet" href="../../../css/mui.css">

        <script src="../../../js/mui.js"></script>

        <style>
            /* list item style */
            
            .item-main-container {
                width: 100%;
                height: 150px;
            }
            
            .item-img {
                width: 100%;
                height: 100px;
            }
            
            .item-text {
                width: 100%;
                height: 50px;
                text-align: center;
            }
            
            body {
                text-align: center;
            }
            /* empty view */
            
            .list-empty-container {
                display: none;
                width: 100%;
            }
            
            .list-empty-img {
                width: 100%;
            }
            
            .list-empty-btn {
                width: 100px;
                margin: 0 auto;
                margin-top: 15px;
                padding: 3px;
                border-radius: 18px;
                font-size: 18px;
                align-content: center;
            }
        </style>
    </head>

    <body style="background: white;">
        <!--下拉刷新容器-->
        <div id="pullrefresh" class="mui-content mui-scroll-wrapper" style="background: white;">
            <div class="mui-scroll">
                <!--数据列表-->
                <ul class="mui-table-view mui-table-view-chevron">
                </ul>
            </div>
        </div>

        <!-- list空 -->
        <div id="listEmptyElm" class="list-empty-container">
            <img class="list-empty-img" src="../../../images/img/list_empty.png" />
            <button class="list-empty-btn">快去逛逛</button>
        </div>

        <script>
            var curPage = 1;
            /**
             * 下拉刷新使用场景
             *     E1.下拉刷新加载第一页,上拉加载更多直到最后一页;
             *     E2.页面开始自动下拉/上拉一次;
             *  E3.无数据页面展示;
             * 
             */
            mui.init({
                pullRefresh: {
                    container: '#pullrefresh',
                    // 双WebView
                    //                    down: {
                    //                        height: 50, // 可选,默认50.触发下拉刷新拖动距离,
                    //                        // 不起作用
                    //                        // auto: true, // 可选,默认false.首次加载自动下拉刷新一次
                    //                        contentdown: "下拉可以刷新", // 可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
                    //                        contentover: "释放立即刷新", // 可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
                    //                        contentrefresh: "正在刷新...", // 可选,正在刷新状态时,下拉刷新控件上显示的标题内容
                    //                        callback: pulldownRefresh
                    //                    },
                    // 单WebView
                    down: {
                        style: 'circle', // 必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
                        color: '#2BD009', // 可选,默认“#2BD009” 下拉刷新控件颜色
                        height: '50px', // 可选,默认50px.下拉刷新控件的高度,
                        range: '100px', // 可选 默认100px,控件可下拉拖拽的范围
                        offset: '0px', // 可选 默认0px,下拉刷新控件的起始位置
                        //auto: true,            // 可选,默认false.首次加载自动上拉刷新一次
                        callback: pulldownRefresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
                    },
                    up: {
                        auto: false, // 可选,默认false.true首次加载自动上拉刷新一次
                        contentrefresh: '正在加载...',
                        callback: pullupRefresh
                    }
                }
            });
            
            mui.plusReady(function(){
                // 代码实现首次自动加载
                // Timeout延时必须
                setTimeout(function() {
                    mui('#pullrefresh').pullRefresh().pullupLoading();
                },50);
            });

            /**
             * 下拉刷新具体业务实现
             */
            function pulldownRefresh() {
                curPage = 1;
                loadPageData();
            }

            var isFirst = true;
            /**
             * 上拉加载具体业务实现
             */
            function pullupRefresh() {
                if(isFirst) {
                    // 首次加载第一页
                    curPage = 1;
                    isFirst = false;
                }
                loadPageData();
            }
            //            if (mui.os.plus) {
            //                mui.plusReady(function() {
            //                    setTimeout(function() {
            //                        mui('#pullrefresh').pullRefresh().pullupLoading();
            //                    }, 10);
            //
            //                });
            //            } else {
            //                mui.ready(function() {
            //                    mui('#pullrefresh').pullRefresh().pullupLoading();
            //                });
            //            }            

            /**
             * 页面数据加载
             *     解耦页面事件
             */
            function loadPageData() {
                getJsonData("url", function(res) {
                    console.log(res.data);
                    parseListData(res.data);
                    curPage++;
                }, function(err) {
                    console.log(err);
                    //                    endPullRefresh(false);
                });
            }

            /**
             * 结束上/下拉刷新
             */
            function endPullRefresh(endMore) {
                mui('#pullrefresh').pullRefresh().endPullupToRefresh(endMore);
                if(!endMore) {
                    mui('#pullrefresh').pullRefresh().refresh(true);
                }
                if(curPage == 1) {
                    mui('#pullrefresh').pullRefresh().endPulldownToRefresh(); //refresh completed
                }
            }

            /**
             * 数据解析
             * @param {Object} params
             */
            function parseListData(params) {
                var table = document.body.querySelector('.mui-table-view');
                if(curPage == 1) {
                    table.innerHTML = "";
                    var pullrefreshElm = document.querySelector("#pullrefresh");
                    var listEmptyElm = document.querySelector("#listEmptyElm");
                    pullrefreshElm.style.display = "block";
                    listEmptyElm.style.display = "none";
                }
                if(curPage == 1 && params.size == 0) {
                    var pullrefreshElm = document.querySelector("#pullrefresh");
                    var listEmptyElm = document.querySelector("#listEmptyElm");
                    pullrefreshElm.style.display = "none";
                    listEmptyElm.style.display = "block";
                } else {
                    for(var i = 0; i < params.list.length; i++) {
                        var itemData = params.list[i];
                        var itemElm = document.createElement('div');
                        itemElm.className = "item-main-container";
                        itemElm.innerHTML = getLayoutElement(itemData.imgUrl, itemData.title);
                        table.appendChild(itemElm);
                    }
                }

                var endMore = false;
                if(params.pageSize != params.size) {
                    endMore = true;
                }
                endPullRefresh(endMore);
            }

            /**
             * 获取布局元素
             * @param {Object} imgUrl
             * @param {Object} title
             */
            function getLayoutElement(imgUrl, title) {
                var elmHtml = `
                        <img class="item-img" src="holderImgUrl" />
                        <div class="item-text">holderTitle</div>
                    `;
                elmHtml = elmHtml.replace("holderImgUrl", imgUrl);
                elmHtml = elmHtml.replace("holderTitle", title);
                return elmHtml;
            }

            var isEmptyList = true;
            /**
             * 数据请求
             * @param {Object} url
             * @param {Object} sucCall
             * @param {Object} failCall
             */
            function getJsonData(url, sucCall, failCall) {
                setTimeout(function() {
                    var jsonObj = {
                        "page": 1,
                        "pageSize": 3,
                        "size": curPage != 3 ? 3 : 1,
                        list: curPage != 3 ? [{
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }, {
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }, {
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }] : [{
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }]
                    }
                    if(isEmptyList) {
                        isEmptyList = false;
                        jsonObj = {
                            "page": 1,
                            "pageSize": 3,
                            "size": 0,
                            list: []
                        }
                    }

                    var result = {
                        data: jsonObj
                    }
                    sucCall(result);
                }, 1000);
            }
        </script>
    </body>

</html>
View Code

 

双WebView完整示例

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">

        <link rel="stylesheet" href="../../../css/mui.css">
        
        <script src="../../../js/mui.js"></script>
        
        <style>
            .float-menu-container{
                position: absolute;
                top: 15px;
                right: 15px;
            }
            .float-menu-btn {
                width: 100px;
                height: 50px;
                font-size: 25px;
                border-radius: 25px;
            }            
        </style>
        
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a id="back" class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 id="title" class="mui-title">上下拉刷新完整实例</h1>
        </header>        
    </body>
    
    <script type="text/javascript">
        //启用双击监听
        mui.init({
            gestureConfig:{
                doubletap:true
            },
            subpages:[{
                url:'dw_sub_page.html',
                id:'dw_sub_page',
                styles:{
                    top: '45px',
                    bottom: '0px',
                }
            }]
        });
    </script>

</html>
View Code

子页面

<!DOCTYPE html>
<html style="background: white;">

    <head>
        <meta charset="utf-8">
        <title>Hello MUI</title>
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">

        <link rel="stylesheet" href="../../../css/mui.css">

        <script src="../../../js/mui.js"></script>

        <style>
            /* list item style */
            
            .item-main-container {
                width: 100%;
                height: 150px;
            }
            
            .item-img {
                width: 100%;
                height: 100px;
            }
            
            .item-text {
                width: 100%;
                height: 50px;
                text-align: center;
            }
            
            body {
                text-align: center;
            }
            /* empty view */
            
            .list-empty-container {
                display: none;
                width: 100%;
            }
            
            .list-empty-img {
                width: 100%;
            }
            
            .list-empty-btn {
                width: 100px;
                margin: 0 auto;
                margin-top: 15px;
                padding: 3px;
                border-radius: 18px;
                font-size: 18px;
                align-content: center;
            }
        </style>
    </head>

    <body style="background: white;">
        <!--下拉刷新容器-->
        <div id="pullrefresh" class="mui-content mui-scroll-wrapper" style="background: white;">
            <div class="mui-scroll">
                <!--数据列表-->
                <ul class="mui-table-view mui-table-view-chevron">
                </ul>
            </div>
        </div>

        <!-- list空 -->
        <div id="listEmptyElm" class="list-empty-container">
            <img class="list-empty-img" src="../../../images/img/list_empty.png" />
            <button class="list-empty-btn">快去逛逛</button>
        </div>

        <script>
            var curPage = 1;
            /**
             * 下拉刷新使用场景
             *     E1.下拉刷新加载第一页,上拉加载更多直到最后一页;
             *     E2.页面开始自动下拉/上拉一次;
             *  E3.无数据页面展示;
             * 
             */
            mui.init({
                pullRefresh: {
                    container: '#pullrefresh',
                    // 双WebView
                    down: {
                        height: 50, // 可选,默认50.触发下拉刷新拖动距离,
                        // 不起作用
                        // auto: true, // 可选,默认false.首次加载自动下拉刷新一次
                        contentdown: "下拉可以刷新", // 可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
                        contentover: "释放立即刷新", // 可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
                        contentrefresh: "正在刷新...", // 可选,正在刷新状态时,下拉刷新控件上显示的标题内容
                        callback: pulldownRefresh
                    },
                    // 单WebView
                    //                    down: {
                    //                        style: 'circle',    // 必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
                    //                        color: '#2BD009',    // 可选,默认“#2BD009” 下拉刷新控件颜色
                    //                        height: '50px',        // 可选,默认50px.下拉刷新控件的高度,
                    //                        range: '100px',        // 可选 默认100px,控件可下拉拖拽的范围
                    //                        offset: '0px',        // 可选 默认0px,下拉刷新控件的起始位置
                    //                        auto: true,            // 可选,默认false.首次加载自动上拉刷新一次
                    //                        callback: pulldownRefresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
                    //                    },
                    up: {
                        auto: true, // 可选,默认false.true首次加载自动上拉刷新一次
                        contentrefresh: '正在加载...',
                        callback: pullupRefresh
                    }
                }
            });

            /**
             * 下拉刷新具体业务实现
             */
            function pulldownRefresh() {
                curPage = 1;
                loadPageData();
            }

            var isFirst = true;
            /**
             * 上拉加载具体业务实现
             */
            function pullupRefresh() {
                if(isFirst) {
                    // 首次加载第一页
                    curPage = 1;
                    isFirst = false;
                }
                loadPageData();
            }
            //            if (mui.os.plus) {
            //                mui.plusReady(function() {
            //                    setTimeout(function() {
            //                        mui('#pullrefresh').pullRefresh().pullupLoading();
            //                    }, 10);
            //
            //                });
            //            } else {
            //                mui.ready(function() {
            //                    mui('#pullrefresh').pullRefresh().pullupLoading();
            //                });
            //            }            

            /**
             * 页面数据加载
             *     解耦页面事件
             */
            function loadPageData() {
                getJsonData("url", function(res) {
                    console.log(res.data);
                    parseListData(res.data);
                    curPage++;
                }, function(err) {
                    console.log(err);
                    //                    endPullRefresh(false);
                });
            }

            /**
             * 结束上/下拉刷新
             */
            function endPullRefresh(endMore) {
                mui('#pullrefresh').pullRefresh().endPullupToRefresh(endMore);
                if(!endMore) {
                    mui('#pullrefresh').pullRefresh().refresh(true);
                }
                if(curPage == 1) {
                    mui('#pullrefresh').pullRefresh().endPulldownToRefresh(); //refresh completed
                }
            }

            /**
             * 数据解析
             * @param {Object} params
             */
            function parseListData(params) {
                var table = document.body.querySelector('.mui-table-view');
                if(curPage == 1) {
                    table.innerHTML = "";
                    var pullrefreshElm = document.querySelector("#pullrefresh");
                    var listEmptyElm = document.querySelector("#listEmptyElm");
                    pullrefreshElm.style.display = "block";
                    listEmptyElm.style.display = "none";
                }
                if(curPage == 1 && params.size == 0) {
                    var pullrefreshElm = document.querySelector("#pullrefresh");
                    var listEmptyElm = document.querySelector("#listEmptyElm");
                    pullrefreshElm.style.display = "none";
                    listEmptyElm.style.display = "block";
                } else {
                    for(var i = 0; i < params.list.length; i++) {
                        var itemData = params.list[i];
                        var itemElm = document.createElement('div');
                        itemElm.className = "item-main-container";
                        itemElm.innerHTML = getLayoutElement(itemData.imgUrl, itemData.title);
                        table.appendChild(itemElm);
                    }
                }

                var endMore = false;
                if(params.pageSize != params.size) {
                    endMore = true;
                }
                endPullRefresh(endMore);
            }

            /**
             * 获取布局元素
             * @param {Object} imgUrl
             * @param {Object} title
             */
            function getLayoutElement(imgUrl, title) {
                var elmHtml = `
                        <img class="item-img" src="holderImgUrl" />
                        <div class="item-text">holderTitle</div>
                    `;
                elmHtml = elmHtml.replace("holderImgUrl", imgUrl);
                elmHtml = elmHtml.replace("holderTitle", title);
                return elmHtml;
            }

            var isEmptyList = true;
            /**
             * 数据请求
             * @param {Object} url
             * @param {Object} sucCall
             * @param {Object} failCall
             */
            function getJsonData(url, sucCall, failCall) {
                setTimeout(function() {
                    var jsonObj = {
                        "page": 1,
                        "pageSize": 3,
                        "size": curPage != 3 ? 3 : 1,
                        list: curPage != 3 ? [{
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }, {
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }, {
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }] : [{
                            title: "自动化测试程序",
                            imgUrl: "https://www.baidu.com/img/bd_logo1.png"
                        }]
                    }
                    if(isEmptyList) {
                        isEmptyList = false;
                        jsonObj = {
                            "page": 1,
                            "pageSize": 3,
                            "size": 0,
                            list: []
                        }
                    }

                    var result = {
                        data: jsonObj
                    }
                    sucCall(result);
                }, 1000);
            }
        </script>
    </body>

</html>
View Code

 

 

参考:

    http://dev.dcloud.net.cn/mui/pullup/

posted @ 2018-01-15 02:02  zhen-Android  阅读(671)  评论(0编辑  收藏  举报