欢迎来到福编程网,本站提供各种互联网专业知识!

移动端翻页插件dropload.js(支持Zepto和jQuery)

发布时间:2016-07-27 作者:小骚木 来源:转载
这篇文章主要为大家详细介绍了移动端翻页插件dropload.js,支持Zepto和jQuery,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

dropload.js提供了最基本的上拉翻页,下拉刷新功能。对于由服务端一次返回所有数据的情况基本通用。

但是,需求往往不是服务端一次性返回所有数据,往往还要支持服务端分页,搜索,排序,多条件筛选等功能。(比较类似美团美食的界面)

一、解决方案

改进1:由于有分页,搜索,排序,多条件筛选功能,可能都不需要上拉,进到页面就没有数据。

例如:搜索一个服务端不存在的名字。

所以,添加接口设置setHasData。

MyDropLoad.prototype.setHasData = function(ishasData) {
  var me = this;
  if (ishasData) {
   me.isData = true;
   me.$domDown.html(me.opts.domDown.domRefresh);
   fnRecoverContentHeight(me);
  } else {
   me.isData = false;
   me.$domDown.html(me.opts.domDown.domNoData);
   fnRecoverContentHeight(me);
  }
 }; 

改进2:由以上问题还引发了一个bug,选择不同的筛选条件,然后上拉加载更多,此时没有反应了。

原因较复杂,举例说明:选择不同的筛选条件,数据量不一样,如果不执行resetload,那么页面的的上拉计算距离就存在问题。

1. 只要发API到服务端,无论返回成功失败,都必须执行resetload,成功时需要在加载完全部新增的数据后resetload。

2. 更改resetload如下,添加调用计算屏幕尺寸的方法。

MyDropLoad.prototype.resetload = function() {
  var me = this;
  if (me.direction == 'down' && me.upInsertDOM) {
   me.$domUp.css({ 'height': '0' }).on('webkitTransitionEnd mozTransitionEnd transitionend', function() {
    me.loading = false;
    me.upInsertDOM = false;
    $(this).remove();
    fnRecoverContentHeight(me);
   });
  } else if (me.direction == 'up') {
   me.loading = false;
   if (me.isData) {
    me.$domDown.html(me.opts.domDown.domRefresh);
    fnRecoverContentHeight(me);
   } else {
    me.$domDown.html(me.opts.domDown.domNoData);
   }
  }
 } 

3. 解决以上两个问题,基本解决了90%的问题,还有一个是setHasData(false)之后的处理。(假设每页的count时20条)

bug: 在筛序条件1:返回20条数据,上拉加载更多返回10条数据,此时设置setHasData(false)。选择筛选条件2,返回20条数据,上拉加载,你会惊奇的发现拉不动了。

why: setHasData(false)之后状态还停留在没有更多数据的状态。此时应该锁定了上拉加载,更改筛选条件后,没有解除锁定,所以不能上拉加载了。

解决方法:每次更改搜索条件,筛选条件,排序等时,都需要设置setHasData(true)。

二、调用方法

整体页面逻辑较复杂。这里在整体解释一遍。

1. 选择要上拉加载的DIV,添加调用方法。

注意事项:

(1)记得保存返回对象。

(2)LoadDownFn时上拉加载后的回调,这里自己要处理的逻辑。我这里时翻页发API,API参数中offset加20,然后发API。

(3)无论API返回失败成功,都必须resetload。

这里强调:

fetchData函数调用发API,失败或者成功都必须self.moreFund.resetload()。

并且失败时直接调用self.moreFund.resetload()即可。成功时要在新的数据返回后,要先用JS动态加载HTML,加载完成后在执行self.moreFund.resetload()。

self.moreFund = $('#table-fundlist').dropload({
 scrollArea: window,
 domDown: {
  domClass: 'dropload-down',
  domRefresh: '
上拉加载更多
', domLoad: '
', domNoData: '' }, loadDownFn: function() { self.apiParams.offset += 20; self.fetchData(true); } });

2. setHasData详解

(1)什么时候需要设置true。

当非翻页API触发之前。即选择新的筛选条件,选择新的搜索字段,选择新的排序字段。这个时候必须setHasData(true)。

this.moreFund.setHasData(true);

(2)什么时候设置false。

服务端返回数据后,比较服务端返回的条目数与API发送的条目数是否一致,不一致设置setHasData(false)。

 if (data.length < this.apiParams.count){      
 this.moreFund.setHasData(false);
 this.moreFund.lock();
} 

3. lock与unlock详解

(1)什么时候设置lock。

服务端返回数据后,比较服务端返回的条目数与API发送的条目数是否一致,不一致设置lock()。

当前页面状态不需要上拉加载时需要设置lock()。例如:在搜索框输入的状态。

(2)什么时候设置unlock。

只有一个地方需要调用。发送API之前设置unlock。

if (self.moreFund) {
 self.moreFund.unlock();
} 

三、JS和CSS源代码

js:

(function($) {
 'use strict';
 var win = window;
 var doc = document;
 var $win = $(win);
 var $doc = $(doc);
 $.fn.dropload = function(options) {
  return new MyDropLoad(this, options);
 };
 var MyDropLoad = function(element, options) {
  var me = this;
  me.$element = $(element);
  me.upInsertDOM = false;
  me.loading = false;
  me.isLockUp = false;
  me.isLockDown = false;
  me.isData = true;
  me._scrollTop = 0;
  me.init(options);
 };
 MyDropLoad.prototype.init = function(options) {
  var me = this;
  me.opts = $.extend({}, {
   scrollArea: me.$element,
   domUp: {
    domClass: 'dropload-up',
    domRefresh: '
下拉刷新
', domUpdate: '
释放更新
', domLoad: '
' }, domDown: { domClass: 'dropload-down', domRefresh: '
上拉加载更多
', domLoad: '
', domNoData: '' //domNoData : '
暂无数据
' }, distance: 50, // 拉动距离 threshold: '', // 提前加载距离 loadUpFn: '', // 上方function loadDownFn: '' // 下方function }, options); if (me.opts.loadDownFn != '') { me.$element.append('
' + me.opts.domDown.domRefresh + '
'); me.$domDown = $('.' + me.opts.domDown.domClass); } if (me.opts.scrollArea == win) { me.$scrollArea = $win; me._scrollContentHeight = $doc.height(); me._scrollWindowHeight = doc.documentElement.clientHeight; } else { me.$scrollArea = me.opts.scrollArea; me._scrollContentHeight = me.$element[0].scrollHeight; me._scrollWindowHeight = me.$element.height(); } $win.on('resize', function() { if (me.opts.scrollArea == win) { me._scrollWindowHeight = win.innerHeight; } else { me._scrollWindowHeight = me.$element.height(); } }); me.$element.on('touchstart', function(e) { if (!me.loading) { fnTouches(e); fnTouchstart(e, me); } }); me.$element.on('touchmove', function(e) { if (!me.loading) { fnTouches(e, me); fnTouchmove(e, me); } }); me.$element.on('touchend', function() { if (!me.loading) { fnTouchend(me); } }); me.$scrollArea.on('scroll', function() { me._scrollTop = me.$scrollArea.scrollTop(); fnRecoverContentHeight(me) if (me.opts.threshold === '') { me._threshold = Math.floor(me.$domDown.height() * 1 / 3); } else { me._threshold = me.opts.threshold; } if (me.opts.loadDownFn != '' && !me.loading && !me.isLockDown && me._threshold != 0 && (me._scrollContentHeight - me._threshold) <= (me._scrollWindowHeight + me._scrollTop)) { fnLoadDown(); } }); function fnLoadDown() { me.direction = 'up'; me.$domDown.html(me.opts.domDown.domLoad); me.loading = true; me.opts.loadDownFn(me); } }; function fnTouches(e) { if (!e.touches) { e.touches = e.originalEvent.touches; } } function fnTouchstart(e, me) { me._startY = e.touches[0].pageY; me.touchScrollTop = me.$scrollArea.scrollTop(); } function fnTouchmove(e, me) { me._curY = e.touches[0].pageY; me._moveY = me._curY - me._startY; if (me._moveY > 0) { me.direction = 'down'; } else if (me._moveY < 0) { me.direction = 'up'; } var _absMoveY = Math.abs(me._moveY); if (me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp) { e.preventDefault(); me.$domUp = $('.' + me.opts.domUp.domClass); if (!me.upInsertDOM) { me.$element.prepend('
'); me.upInsertDOM = true; } fnTransition(me.$domUp, 0); if (_absMoveY <= me.opts.distance) { me._offsetY = _absMoveY; me.$domUp.html(me.opts.domUp.domRefresh); } else if (_absMoveY > me.opts.distance && _absMoveY <= me.opts.distance * 2) { me._offsetY = me.opts.distance + (_absMoveY - me.opts.distance) * 0.5; me.$domUp.html(me.opts.domUp.domUpdate); } else { me._offsetY = me.opts.distance + me.opts.distance * 0.5 + (_absMoveY - me.opts.distance * 2) * 0.2; } me.$domUp.css({ 'height': me._offsetY }); } } // touchend function fnTouchend(me) { var _absMoveY = Math.abs(me._moveY); if (me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp) { fnTransition(me.$domUp, 300); if (_absMoveY > me.opts.distance) { me.$domUp.css({ 'height': me.$domUp.children().height() }); me.$domUp.html(me.opts.domUp.domLoad); me.loading = true; me.opts.loadUpFn(me); } else { me.$domUp.css({ 'height': '0' }).on('webkitTransitionEnd transitionend', function() { me.upInsertDOM = false; $(this).remove(); }); } me._moveY = 0; } } // 重新获取文档高度 function fnRecoverContentHeight(me) { if (me.opts.scrollArea == win) { me._scrollContentHeight = $doc.height(); } else { me._scrollContentHeight = me.$element[0].scrollHeight; } } MyDropLoad.prototype.lock = function(direction) { var me = this; if (direction === undefined) { if (me.direction == 'up') { me.isLockDown = true; } else if (me.direction == 'down') { me.isLockUp = true; } else { me.isLockUp = true; me.isLockDown = true; } } else if (direction == 'up') { me.isLockUp = true; } else if (direction == 'down') { me.isLockDown = true; } }; MyDropLoad.prototype.unlock = function() { var me = this; me.isLockUp = false; me.isLockDown = false; }; MyDropLoad.prototype.setHasData = function(ishasData) { var me = this; if (ishasData) { me.isData = true; me.$domDown.html(me.opts.domDown.domRefresh); fnRecoverContentHeight(me); } else { me.isData = false; me.$domDown.html(me.opts.domDown.domNoData); fnRecoverContentHeight(me); } }; MyDropLoad.prototype.resetload = function() { var me = this; if (me.direction == 'down' && me.upInsertDOM) { me.$domUp.css({ 'height': '0' }).on('webkitTransitionEnd mozTransitionEnd transitionend', function() { me.loading = false; me.upInsertDOM = false; $(this).remove(); fnRecoverContentHeight(me); }); } else if (me.direction == 'up') { me.loading = false; if (me.isData) { me.$domDown.html(me.opts.domDown.domRefresh); fnRecoverContentHeight(me); } else { me.$domDown.html(me.opts.domDown.domNoData); } } }; function fnTransition(dom, num) { dom.css({ '-webkit-transition': 'all ' + num + 'ms', 'transition': 'all ' + num + 'ms' }); } })(window.Zepto || window.jQuery);

CSS:

.dropload-up,
.dropload-down {
 background-color: #F0EFF5;
 position: relative;
 height: 0;
 overflow: hidden;
}

.dropload-down {
 height: 50px;
 border-top: 1px solid #e5e5e5;
}

.dropload-refresh .drop-up-icon,
.dropload-refresh .drop-down-icon,
.dropload-update .drop-up-icon,
.dropload-update .drop-down-icon {
 vertical-align: text-bottom;
 margin-right: 3px;
 height: 16px;
 width: 12px;
}

.dropload-load .loading-icon {
 vertical-align: middle;
 height: 20px;
 width: 20px;
}

.dropload-refresh span,
.dropload-update span {
 vertical-align: middle;
 line-height: 18px;
 font-size: 16px;
 color: #585858;
}

.dropload-noData {
 border-bottom: 1px solid #e5e5e5;
 background-color: #FFFFFF;
}

.dropload-noData span {
 line-height: 18px;
 font-size: 14px;
 color: #999999;
}

.dropload-refresh,
.dropload-update,
.dropload-load,
.dropload-noData {
 position: absolute;
 width: 100%;
 height: 50px;
 bottom: 0;
 line-height: 50px;
 text-align: center;
}

.dropload-down .dropload-refresh,
.dropload-down .dropload-update,
.dropload-down .dropload-load {
 top: 0;
 bottom: auto;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持全福编程网。

相关推荐