• 基于Zepto移动端下拉加载(刷新),上拉加载插件开发


    写在前面:本人水平有限,有什么分析不到位的还请各路大神指出,谢谢。

    这次要写的东西是类似于<今日头条>的效果,下拉加载上啦加载,这次做的效果是简单的模拟,没有多少内容,下面是今日头条的移动端截图:

    1. 先说一个题外话,拿到这个效果后,先分析了下,由于新闻分类很多,每个类目下都得有很多新闻,并且加载的时候得用ajax,所以得分清在哪个栏目下触发的加载,然后挑出相应的接口数据,插入到那个页面。

    先分析一下:这个效果类似选项卡,但是简单的选项卡是把选项卡子内容全部写在文档内部(页面加载的时候会把所有的资源都加在进来),通过display:none/block;来控制显示,通过js处理可以达到下拉上拉加载的效果。但是这个新闻类页面图片资源比较多,在移动端加载大量资源会费时,费流量(不止自己的流量,服务器也需要流量),所以我们把这个项目下面的内容拆分为每个单页面。今日头条项目中每个类型在切换的时候都会先清空之前的内容,在重新插入,这个拆分单页面在类型切换,页面刷新时无疑会造成数据丢失,他们(每日头条开发者)的做法是吧数据写在了缓存里面(最下面有图,朋友们也可以自己去打开看看)。

    开始写插件,插件结构如下:

    ;
    (function($,window,document,undefined){//传值,多传的忽略
        'use strict'//使用严格模式
        //定义插件名称
        var plugingName='slideDownRefresh',
        defaults={
            //默认 配置项 如果使用者不写自己加上
            'width':'300px'
        }
    
        // 属性:
        function Plugin(element,options){
            //element 为节点,options是执行的快慢,宽高呀配置项
            //console.log(element);//测试是否正确
            this.element = element;
            // this.options = options;//得检测下看看 使用者是否佳丽参数
            this.options = $.extend({},defaults,options);//如果options没有就用defaults,如果options有就把defaults的给替换
            // console.log(this.options);
        }
        //方法:
        Plugin.prototype={
            init:function(){
    
            },
            eventHandle:function(){
    
            }
        }
        // 把插件绑定到Zepto上:
        $.fn[plugingName]=function(options){
            return this.each(function(){//遍历匹配的元素,此处的this表示为jquery对象,而不是dom对象 
                // 因为 应该有多个地方用到这个插件 
                //zepto 的data与jquery的data有区别日后再说
                if( !$(this).data('plugin_' + plugingName)) {
                    return $(this).data('plugin_'+plugingName,new Plugin(this,options))
                }
            })
        }
    })(Zepto,window,document);

    接下来补充插件的事件等:

    ;
    (function($,window,document,undefined){//传值,多传的忽略
        'use strict'//使用严格模式
        //定义插件名称
        var plugingName = 'slideDownRefresh',
        defaults = {
            //默认 配置项 如果使用者不写自己加上
            'width':'300px'
        }
        // 属性:
        function Plugin(element,options){
            //element 为节点,options是执行的快慢,宽高呀配置项
            //console.log(element);//测试是否正确
            this.element = element;
            // this.options = options;//得检测下看看 使用者是否佳丽参数
            this.options = $.extend({},defaults,options);//如果options没有就用defaults,如果options有就把defaults的给替换
            // console.log(this.options);
    
            // 执行以下,初始化调用一下
            this.init();
            this.eventHandle();
        }
        //方法:
        Plugin.prototype = {
            init: function(){
                this.$refresh = $(this.element).find('.refresh');//找到标签
                this.$rotate = $(this.element).find('img');//找到旋转标签
                this._start = 0;//旋转的初始值
                this._end = 0;//旋转的结束值
            },
    
            // 事件主要为移动端touch事件,下面会写到,不懂得可以取查阅资料
            eventHandle: function(){
                this.touchStart(this.element);
            },
            touchStart: function(ele){
                var _self=this;//把this存起来,不用来回反复取(节约性能);
                $(ele).on('touchstart', function(e){
                    var touch = e.targetTouches[0];//只允许一个手指触碰
                    _self._start = touch.pageY;//获取点上去时的纵坐标
                    _self.touchMove(_self.element);//调用移动方法
                })
            },
            touchMove: function(ele){
                var _self=this;//把this存起来,不用来回反复取(节约性能);
                $(ele).on('touchmove', function(e){
                    var touch = e.targetTouches[0];//只允许一个手指触碰
                    _self._end = _self._start - touch.pageY;//获取移动的纵坐标距离
                    _sliding.call(_self,_self._end);
                    //这里之所以不用_sliding.()调用是因为,这样传的this为touchmove的this,而我们要的this为:_self
                    _self.touchEnd(_self.element);
                });
                // 写个私有方法
                function _sliding(dist){
                    // dist为距离
                    _self.$refresh.css('transform', 'translate3d(0,'+ -dist + 'px, 0)');//拿到结点 写动画
                    _self.$rotate.css('transform','rotate('+ (-dist * 4) + 'deg)');//让load转起来这里的4只是随便写的,可以任意写,怎么好看怎么写
                }
            },
            touchEnd: function(ele){
                var _self=this;//把this存起来,不用来回反复取(节约性能);
                $(ele).on('touchend', function(e){
                    if(_self._end < -160){
                        // 这个数字可以随便设置 成功时
                        _slided.call(_self);
                        setTimeout(function(){
                            _reset.call(_self);
                        },3000);
                    }else{
                        //距离不够
                        _noslide.call(_self);
                    }
                    // 事件全部执行完以后,把事件全部移除
                    $(this).unbind('touchmove');
                    $(this).unbind('touchend');
                });
                function _slided(){// 下拉,然后松开,然后执行
                    _self.$refresh.addClass('refreshing');
                    _self.$rotate.addClass('index');
                };
                // 下滑距离不够时,复原 但是不算新
                function _noslide(){
                    _self.$refresh.addClass('refreshing');
                    _self.$rotate.addClass('index');
                    _self.$refresh.css('transform', 'translate3d(0,0,0)');
                    _self.$rotate.css('transform',  'rotate(0deg)');
                    // 移除加的class
                    setTimeout(function(){
                        _self.$refresh.removeClass('refreshing');
                        _self.$rotate.removeClass('index');
                    },500);
                };
                // 刷新完成,回到原来状态
                function _reset(){
                    _self.$refresh.css('transform', 'translate3d(0,0,0)');
                    _self.$rotate.css('transform',  'rotate(0deg)');
    
                    setTimeout(function(){
                        _self.$refresh.removeClass('refreshing');
                        _self.$rotate.removeClass('index');
                        // window.location.reload(); //刷新页面,或者执行ajax 调取数据
                        
                        // 调用数据
                        $.ajax({
                            url:,
                            data:url,
                            success:function(data){
                                var list=defaults.redenr(data);
                                $("...").append(list);
                            }
                        })
                    },500);
                }
            }
        }
        // 把插件绑定到Zepto上:
        $.fn[plugingName] = function(options){
            return this.each(function(){//遍历匹配的元素,此处的this表示为jquery对象,而不是dom对象 
                // 因为 应该有多个地方用到这个插件 
                //zepto 的data与jquery的data有区别日后再说
                if( !$(this).data('plugin_' + plugingName)){
                    return $(this).data('plugin_' + plugingName, new Plugin(this,options))
                }
            })
        }
    })(Zepto,window,document);

     调用代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基于Zepto移动端下拉刷新(加载),上拉加载插件开发</title>
        <meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0,user-scalable=no">
        <style>
            *{
                padding:0;
                margin:0;
            }
            a{
                text-decoration: none;
            }
            li{
                list-style: none;
            }
            header{
                100%;
                height: 40px;
                line-height: 40px;
                position: fixed;
                top:0;
                left: 0;
                background: #fff;
                z-index: 100;
            }
            header li{
                display: inline-block;
                24%;
            }
            header li a{
                text-align: center;
                 100%;
                display: block;
                color:#000;
                height: 40px;
            }
            .refresh{
                 100%;
                position: absolute;
                text-align: center;
            }
            .refresh img{
                 40px;
            }
            .warp{
                 100%;
                clear: both;
            }
            .refreshing{
                transition: all .5s ease-in-out;
                -webkit-transition: all .5s ease-in-out;
            }
            .refresh img.index{
                -webkit-animation:today 3s infinite;
                animation:today 3s infinite;
            }
            @keyframes today{
                0%{
                    transform:rotate(0deg);
                }
                100%{
                    transform:rotate(-2000deg);
                }
            }
            @-webkit-keyframes today{
                0%{
                    -webkit-transform:rotate(0deg);
                }
                100%{
                    -webkit-transform:rotate(-2000deg);
                }
            }
        </style>
    </head>
    <body>
        <div class="warp">
            <header>
                <ul>
                    <li><a href="#tuijian" class="tuijian">推荐</a></li>
                    <li><a href="#junshi" class="junshi">军事</a></li>
                    <li><a href="#jingji" class="jingji">经济</a></li>
                    <li><a href="#shehui" class="shehui">社会</a></li>
                </ul>
            </header>
            <div class="refresh">
                <img src="img/re.png" alt="">
            </div>
            <section id="content">
                <li>测试内容</li>
                <li>测试内容</li>
            </section>
        </div>
        
    </body>
    <script src="http://apps.bdimg.com/libs/zepto/1.1.4/zepto.js"> </script>
    <script src="js/myDemo.js"></script>
    <script>
    $('.warp').slideDownRefresh({
        'width':'800px',
        'url':,//这个url 为要添加新数据的url
        redenr:function(data){
            //在这里拼接页面
            var list=null;
            return list;
        }
    });
    
    </script>
    </html>

     总结:这个插件只是写了下拉,上啦加载的可以在 touchEnd 函数中判断是上滑还是下滑来判断加载。 本插件在单页中没什么问题,要是放在 今日头条这样的项目中就得补充插件内容了。

    分析今日头条:今日头条的每个新闻项目的切换 相应的url也会变化,项目来回切换的时候 各种新闻数据还是不变的,即便F5刷新 各个新闻数据还是不变的。于是我找了下缓存还有发现了新闻的缓存。

    所以本插件还得添加一个功能:把拿来的数据添加到缓存中。 类似的还有《微信热文》也是这个原理实现的。

    欢迎大家指出问题,项目下载地址https://github.com/WangMaoling/refresh

  • 相关阅读:
    redis导入导出工具redisdump,centos7安装使用
    mysql 锁表情况,处理笔记
    python语言
    pythonhello world
    常用单词
    Django课堂笔记 1
    JS之随机点名系统
    js之简易计算器
    JS之放大镜效果
    SQLServer索引漫谈
  • 原文地址:https://www.cnblogs.com/wangmaoling/p/6524759.html
Copyright © 2020-2023  润新知