我们发现美丽说、花瓣网都是无限拖的翻页效果,用户拖动似乎永不停止,这对于女性比较适合,但并不适合所有用户,特别是男性用户,并不喜欢没有止境的工作。因此,什么值得买的翻页加载方式更令人喜欢,即往下拖动可以自动加载3-5页,然后出现翻页导航,让读者可以点击导航来实现翻页。
为此,否子戈制作了一个jQuery插件,来实现这个效果。为了让开发者了解这个插件,这里详细的讲解一下开发的思路。
一、创建一个jQuery插件的基本框架 ↑
首先,你需要了解如何自定义自己的jQuery插件,构建一个自己的jQuery框架。不过乌徒帮之前的自定义方法明显不够全面,我们这里介绍一个简单的构建方法。
(function(jQuery) {?? ? ? jQuery.pagenavajax = function(options) {?? ? ? }; ? // 插件的defaults?? ? ? jQuery.pagenavajax.defaults = { ? }; })(jQuery);
之所以选择使用jQuery.pagenavajax而非jQuery.fn.pagenavajax,是为参数扩展做准备,以实现更多且更易读的代码量。
二、为翻页拖插件策划参数 ↑
很少有人在创建插件的时候考虑策划问题,但否子戈认为凡事预则立不预则废,我们必须先想清楚这个插件要执行哪些动作,而之所以先策划参数,也是从方便的角度出发。即我在使用这个插件的时候,希望哪些变量是我自己可以控制的。我则设立了下列参数,基本可以满足我自己的需求。
loading_html : '<div>Loading...</div>', // 拖到底部时提示正在加载的HTML代码 pagenav : '#pagenav', // 翻页导航容器,下文会说到插件使用的HTML代码结构 container : '#post-list', // 翻页要加载的列表容器,下文会说到插件使用的HTML代码结构 pendObj : 'div.post', // 翻页要加载的列表项目,例如每条文章的容器,下文也会演示 startPos : 50, // 从什么时候开始触发动作,这里默认是距离页面底部50像素的时候开始加载下一页 currentNav : 'span.current', // 翻页导航中,当前页面的容器 real_current_page : 1, // 当前页面是第几页 nav_page_num : 3, // 向后翻几页就停止继续翻页拖,直接显示翻页导航按钮,设置为false的话就是无限拖 call_back_fun : null // 回调函数,每次执行动作完成之后要进行什么处理,使用function(){}
看上去有些参数显得复杂,但我个人认为是必要的,例如real_current_page,如果你不设置的话,nav_page_num怎么知道是从第几页开始往后翻的呢?
三、翻页插件动作流程 ↑
整个翻页的流程其实也很简单,我们通过监控滚动条的滚动,当距离页面还有startPos个像素的时候,开始执行动作。通过ajax向currentNav之后的<a>标签的href值所在页面发出请求,从返回的对象中取出pendObj,并将它们加载到container最后,同时从获得的数据中获得pagenav,覆盖掉原来的,这样就像是一个新的页面。
1、初始化参数 ↑
通过extend来初始化上述的参数。不过由于插件动作和参数是分离的,我们需要注意它的具体使用。
var opts = jQuery.extend({}, jQuery.pagenavajax.defaults, options);
这样一来,所有的参数都被负值到opts对象中,使用opts.pagenav的形式来获取参数。但为了更方便的使用它们,我们也可以再次赋值。
pagenav = opts.pagenav,container = opts.container,pendObj = opts.pendObj, startPos = opts.startPos, currentNav = opts.currentNav, loading_html = opts.loading_html, real_current_page = opts.real_current_page, nav_page_num = opts.nav_page_num;
这样就可以使用pagenav来代表参数中的值,但需要理解的是,我们给定的参数pagenav跟这里的pagenav本质并不相同。
2、监听滚动事件 ↑
通过监听浏览器的滚动,来进行判断和触发动作
jQuery(window).bind('scroll',function(){ ? ... ? if(jQuery(pagenav).length > 0){ ??? if(jQuery(pagenav).offset().top - $scrollTop - $windowHeight < startPos){ ????? ... ????? if($nextPage.prop('tagName') != 'A'){ // 如果当前页面下一个不是<a>,代表这是最后一页了 ??????? ... ??????? return false; ????? } ????? if(!nav_page_num && parseInt($nextPage.text()) - real_current_page > nav_page_num){ // 如果设置了只翻多少页就停止加载的话 ???????? ... ??????? return false; ????? } ????? ... ????? $nextPageLink = $nextPage.attr('href'); ????? $ajax = jQuery.ajax({ ??????? url : $nextPageLink, ??????? type : 'get', ??????? dataType : 'html', ??????? beforeSend : function(){}, ??????? success : function(data){ ????????? ... ????????? typeof opts.call_back_fun == 'function' && opts.call_back_fun.call(this); // 执行回调函数 ??????? } ????? }); ???? } ? } }).scroll();
在上面的省略号的地方就是我们的执行动作,通过这些动作来实现1中所说的各种加载。
3、注意加载的可能性错误 ↑
在以往的经验中,我们常常会发现一般的ajax翻页拖会一不小心加载两次三次,这主要是因为当我们把页面拖到距离底部一定像素的时候,我们会发现这个时候由于时间差,可能触发多次ajax,导致多次加载下一页。因此,我们需要通过一些特殊手段来防止这种重复加载。
我的办法是,在第一次触发ajax时,为pagenav增加一个data-scroll属性,如果这个属性值不为空或0,就说明ajax正在进行,不能执行第二次ajax,而一旦ajax执行成功,就将data-scroll设置为0,可以继续执行下一个ajax。并通过下面的代码来判断:
if(jQuery(pagenav).attr('data-loading') == '1'){ ??? return false; }
4、增加一个可以无限加载的按钮 ↑
这个小点是新增的内容,之前的插件当我们拖到规定的页码之后,就不再继续ajax加载,直接将翻页导航按照原来的格式进行显示。但我们试图通过一个按钮来实现当用户看到这个显示出来的翻页导航之后,仍然可以继续往下ajax加载,且不会再终断,直到用户离开这个页面。
在typeof opts.call_back_fun == 'function' && opts.call_back_fun.call(this);这段代码下一行增加下面的代码:
jQuery(pagenav).append('<span style="display:none;padding-left:0;padding-right:0;" id="pagenavajax-forever"><a href="javascript:void(0);" style="border:0;color:#930E03;margin:0;">无限加载</a></span>') jQuery(pagenav + ' #pagenavajax-forever').css('display','inline');
之所以要在回调函数执行完成之后再增加这个按钮,是担心回调函数会抓取#pagenav.html(),如果提前增加这个按钮,可能导致#pagenav.html()中会多出不想要的这些新代码。
接下来,我们通过触发按钮的click事件来使其生效。我们利用了代码中原有的一个参数nav_page_num来实现:
jQuery('#pagenavajax-forever a').live('click',function(){ ??? opts.nav_page_num = false; ??? jQuery(window).scroll(); });
如此一来,点击这个按钮就能继续无限的拖了。
四、整个翻页拖插件的代码即提供下载 ↑
为了方便所有人使用,我将插件打包上传到网盘,提供给所有人下载。
老规矩,下面的内容需要赞助之后才能阅读,你的支持对我来说是无上荣耀。
[pay4read price="10" title="jQuery ajax无限拖翻页插件"]
(function(jQuery) {?? ? ? // 本插件由否子戈制作,发布与乌徒帮 http://www.utubon.com/jquery-plugin-pagenav-ajax/ // 插件的定义?? ? ? jQuery.pagenavajax = function(options) {?? ? ??? //debug(this); ??? // build main options before element iteration?? ? ??? var opts = jQuery.extend({}, jQuery.pagenavajax.defaults, options); ??? // iterate and reformat each matched element?? ? ??? jQuery(window).bind('scroll',function(){ ????? var $window = jQuery(window),$windowHeight = $window.height(), ??????? $scrollTop = $window.scrollTop(), ??????? $document = jQuery(document),$documentHeight = $document.height(), ??????? pagenav = opts.pagenav,container = opts.container,pendObj = opts.pendObj, ??????? startPos = opts.startPos, ??????? currentNav = opts.currentNav, ??????? loading_html = opts.loading_html, ??????? real_current_page = opts.real_current_page, ??????? nav_page_num = opts.nav_page_num; ????? if(jQuery(pagenav).length > 0){ ??????? if(jQuery(pagenav).offset().top - $scrollTop - $windowHeight < startPos){ ????????? $nextPage = jQuery(pagenav).find(currentNav).next(); ????????? if($nextPage.prop('tagName') != 'A'){ ??????????? //alert($nextPage.prop('tagName')); ??????????? jQuery(pagenav).remove(); ??????????? return false; ????????? } ????????? if(!nav_page_num && parseInt($nextPage.text()) - real_current_page > nav_page_num){ ??????????? //$ajax.abort(); ??????????? return false; ????????? } ????????? if(jQuery(pagenav).attr('data-loading') == '1'){ ??????????? return false; ????????? } ????????? $nextPageLink = $nextPage.attr('href'); ????????? $ajax = jQuery.ajax({ ??????????? url : $nextPageLink, ??????????? type : 'get', ??????????? dataType : 'html', ??????????? beforeSend : function(){ ????????????? jQuery(pagenav).attr('data-loading','1'); ????????????? jQuery(pagenav).append(loading_html).find('span,a').hide(); ?????????? }, ??????????? success : function(data){ ????????????? $postList = jQuery(data).find(container + ' ' + pendObj); ????????????? $postList.appendTo(container).hide().fadeIn(); ????????????? $pageNav = jQuery(data).find(pagenav).html(); ????????????? jQuery(pagenav).html($pageNav); ????????????? jQuery(pagenav).attr('data-loading','0'); ????????????? typeof opts.call_back_fun == 'function' && opts.call_back_fun.call(this); ??????????? } ????????? }); ??????? } ????? } ??? }).scroll(); ? }; ? // 插件的defaults?? ? ? jQuery.pagenavajax.defaults = {?? ? ??? loading_html : '<div>Loading...</div>', ??? pagenav : '#pagenav', ??? container : '#post-list', ??? pendObj : 'div.post', ??? startPos : 50, ??? currentNav : 'span.current', ??? real_current_page : 1, ??? nav_page_num : 3, ??? call_back_fun : null ? }; })(jQuery);
[/pay4read]
由于本插件倾注了大量精力,并会在将来继续更新。请随时关注本文的更新情况。
五、在网站中如何使用和配置 ↑
虽然插件已经发布,但具体如何使用呢?本插件需要遵循一些规则,首先是HTML结构代码。
<#post-list> ?? ?<div.post> ?? ?<div.post> ?? ?... ?? ?<div.post> ?? ?<div.post> </#post-list> <#pagenav> ?? ?<a><a><a><span.current><a><a> </#pagenav>
上面的HTML代码只是一种示意,你也可以规定自己的container,只要在下面的初始化参数配置中规定即可。
<script src="<?php bloginfo('template_url'); ?>/js/pagenavajax.js"></script> <script> jQuery.pagenavajax({ ??? loading_html : '<img src="<?php bloginfo('template_url'); ?>/images/loading.gif" style="clear:both;display:block;margin:0 auto;" alt="正在加载..." />', ?? ?pagenav : '#pagenav', ?? ?container : '#post-list', ?? ?pendObj : 'div.post', ?? ?startPos : 50, ?? ?currentNav : 'span.current', ?? ?real_current_page : <?php echo (get_query_var('paged') ? get_query_var('paged') : 1); ?>, // 这里是通过wordpress内部的机制获取当前的页码 ?? ?nav_page_num : 3, ?? ?call_back_fun: function(){ ?? ??? ?if($('#pagenav').length > 0){ ?? ??? ??? ? $newpagenavhtml = $('#pagenav').html(); // 因为经过替换,所以$('#pagenav').html()和执行动作之前已经不同了 ?? ??? ? } ?? ?} }); </script>
今天在处理一个主题时,发现无限加载按钮失效,原因是将这段调用代码放在了header.php中,如果换到footer.php中则正常。造成这个问题的原因应该是DOM加载顺序的问题,在插件中绑定click事件,但DOM还没有加载完成,如果将插件中的live('click'放在ready中或许就可以正常运作。当然,其实你也可以在ready之后再运行插件,如下:
jQuery(document).ready(function(){ jQuery.pagenavajax({}); // 将运行动作放在ready之后,DOM已经加载完成,因此可以正常触发click事件 });
好了,关于jQuery ajax无限拖翻页,翻特定页数后显示翻页导航的具体实现过程就分享到这里,或许插件中还存在一些具体细节的问题,还需要您及时反馈及时修正。
非常的不错