(转)jQuery插件编写学习+实例——无限滚动

原文地址:http://www.cnblogs.com/nuller/p/3411627.html

 

  最近自己在搞一个网站,需要用到无限滚动分页,想想工作两年有余了,竟然都没有写过插件,实在惭愧,于是简单学习了下jQuery的插件编写,然后分享出来。

 

先说下基础知识,基本上分为两种,一种是对象级别的插件,另一种是全局级别的插件。对象级别的插件就像是实例方法,它是属于实例对象的,而全局级别的相当于静态方法,是属于类的,调用起来自然也就不一样,对于全局级别的插件我们自然是使用jQuery来调用,比如$.NPScrollLoad(....),对象级别的插件自然是应用与jQuery对象上了,比如:$("selector").NPScrollLoad(...)。这个不难理解吧。

对于$.NPScrollLoad()这种形式,我们要对jQuery进行扩展,怎么扩展呢,很简单,就像给对象赋值一样

方法1:

方法2:

这就是在博客园,发布博客界面测试的,F12打开开发者工具,切换到Console,先输入运行"$",确认页面引入了jQuery,然后扩展jQuery,一种方法是直接给属性名赋值$.youname = function(){...},另一种方法是使用$.extend({yourname:function(){...}}),使用哪种看个人喜好。

 

对于$("selector").NPScrollLoad()这种方式,扩展就不是jQuery本身了,而是jQuery.fn:

方法1:

方法2:

和全局级别的插件方法区别就是扩展的时$.fn而不是$。

 

因为各式各样的插件很多,属性重名的概率很高,为了避免这样那样的问题,我们使用闭包来写插件,从而使插件的变量和function和其他的不互相影响,这个我尽量简化:

复制代码
 1 ;(function($) {
 2     // jQuery扩展
 3     $.youname = function([args]) {
 4         // TODO
 5     };
 6     // 或者
 7     $.extend({
 8         youname : function() {
 9             // TODO
10         }
11     });
12     
13     // jQuery对象扩展
14     $.fn.youname = function([args]) {
15         // TODO
16     };
17     // 或者
18     $.fn.extend({
19         youname : function() {
20             // TODO
21         }
22     });
23 }) (jQuery);
复制代码

 

为什么要这样写?看下面的例子你就明白了:

这个其实就相当于我们直接执行一个匿名函数,并且传递给他一个参数,比如上面的例子就是,我们定义了一个匿名函数用来alert传进去的参数,然后我们给它传递"hello!",它就会马上执行,把插件的相关方法写到这里面并且引入这个js文件的话也就会在第一时间把我们的插件扩展到jQuery上,从而可以直接使用,并且可以保护我们的代码不受外面代码影响,也不会污染其他的代码。为了防止以后压缩代码的时候出错,所以最好在前后都加上一个分号";"。

 

为了让我们的插件足够通用,我们需要把一些配置留给用户自己定义,通用的做法是使用一个对象来承载所有的设置项,并给他们默认值。

1 var defaults = {
2     msg1: "hello1",
3     msg2: "hello2"
4 }

然后我们给我们的插件函数加上参数:

复制代码
 1 ;(function($) {
 2     var defaults = {
 3     msg1: "hello1",
 4     msg2: "hello2"
 5     };
 6 
 7     $.NPScrollLoad = function(options) {
 8         var opts = $.extend(defaults, options);
 9         alert(opts.msg1 + opts.msg2);
10     };
11 
12 }) (jQuery);
复制代码

 

然后就可以调用了

$.NPScrollLoad({msg1 : "你好"});
$.NPScrollLoad({msg1 : "你好", msg2 : "呵呵"});
$.NPScrollLoad({msg2 : "......"});
$.NPScrollLoad();

没有赋值的属性会使用defaults里面定义的默认值,赋值的属性则会覆盖defaults中相应的属性。

 

下面是我写的插件代码,代码有些地方比较拙劣,懒得设计和修改了。。。

复制代码
 1 /**
 2  * 无限滚动
 3  * 作者:Null Pointer
 4  */
 5  ;(function($) {
 6     $.NPScrollLoad = function(options) {
 7         // var opts = $.extend($.NPScrollLoad.defaults, options);
 8         $.NPScrollLoad.defaults = $.extend($.NPScrollLoad.defaults, options);
 9         return $(window).scroll(function() {
10             processor.process();
11         });
12     };
13 
14     var processor = {
15         timeoutId: null,
16         process: function () {
17             clearTimeout(this.timeoutId);
18             this.timeoutId = setTimeout(function () {
19                 loadData();
20             }, 400);
21         }
22     };
23 
24     /**
25      * 加载数据
26      */
27     function loadData() {
28         if (($(document).height() - ($(document).scrollTop() + $(window).height())) <= $.NPScrollLoad.defaults.offsetPixelToLoad) {
29             $(window).unbind("scroll");
30             $.NPScrollLoad.preLoad();
31             $.post(
32                 $.NPScrollLoad.defaults.url,
33                 { pageIndex : $.NPScrollLoad.defaults.pageIndex },
34                 function (data) {
35                     $.each(data, function (i, item) {
36                         $.NPScrollLoad.handleResult(item);
37                     });
38                     $.NPScrollLoad.afterLoad();
39                     $.NPScrollLoad.defaults.pageIndex++;
40                     if (data.length < $.NPScrollLoad.defaults.pageSize) {
41                         $.NPScrollLoad.noMoreData();
42                     } else if ($.NPScrollLoad.defaults.pageIndex == $.NPScrollLoad.defaults.maxPage) {
43                          $.NPScrollLoad.reachMaxPage();
44                     } else {
45                         $(window).bind("scroll", processor.process)
46                     }
47                 }
48             );
49         }
50     };
51 
52 
53     /**
54      * 处理
55      */
56     $.NPScrollLoad.handleResult = function(jsonItem) {
57 
58     };
59 
60     /**
61      * 加载之前
62      */
63     $.NPScrollLoad.preLoad = function() {
64         $("#loading").fadeIn();
65     };
66 
67     /**
68      * 加载之后
69      */
70     $.NPScrollLoad.afterLoad = function() {
71         $("#loading").fadeOut();
72     };
73 
74     /**
75      *  无更多数据
76      */
77     $.NPScrollLoad.noMoreData = function() {
78         $("#nomoreresult").fadeIn();
79     };
80 
81     /**
82      * 到达最大页数
83      */
84     $.NPScrollLoad.reachMaxPage = function() {
85         $("#loadmore").show();
86     };
87 
88     $.NPScrollLoad.defaults = {
89         /* 距离底部距离(开始加载数据) */
90         offsetPixelToLoad : 100,
91         url : "",
92         pageSize : 10,
93         maxPage : 5,
94         pageIndex : 1
95     };
96 
97 })(jQuery);
复制代码

 

 

代码中有一部分是我之前没有说到的细节:

1.我把defaults定义成$.NPScrollLoad.defaults这样用户可以在外部直接设置默认值,比如$.NPScrollLoad.defaults.url = "text.aspx";这样就行了。

2.在(function($){})(jQuery)内部定义的function是私有的,只有此function内可以访问,比如loadData就只可以在此匿名函数内部访问。

3.我把部分function写成jQuery的扩展,用户就可以在外部访问,或者自定义,比如$.NPScrollLoad.handleResult这样就可以间接实现类似于函数重写的功能,让用户自定义部分操作。

4.第九行我加了一个return,这里是为了延续jQuery的链式调用,比如$("selector").val("abc").attr("id", "aaa")。。。。因为jQuery的函数本身都是返回自身的,所以$(window).scroll()也会返回$(window),所以最后的return可以延续其链式调用特性,不过,因为我写的是全局扩展,所以也就谈不上链式调用了。。。这个对于对象扩展还是有一定重要性的。

5.定义processor对象是因为实时监听scroll事件灰常消耗资源,没滑过1px都会触发事件,所以加个延迟时间,让其一定时间内如果触发的话就取消前一次事件。代码应该不难理解。

下面是调用代码:

复制代码
1 <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.10.2.min.js"></script>
2 <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.NPScrollLoad.1.0.js"></script>
3 <script type="text/javascript">
4 $(function() {
5     var contextPath = "${pageContext.request.contextPath}";
6     $.NPScrollLoad({url:contextPath + "/ajaxPage/home"});
7 });
8 </script>
复制代码

 

 

本来还想排版,这么晚了,算了,睡觉了。

 

posted on 2013-11-09 09:42  黑子范  阅读(217)  评论(0编辑  收藏  举报

导航