5

第一次写jquery插件,在这里做一个记录和积累。所有文章均同步到我的博客

写jQuery插件的目的

主要是对一些重复使用率高的一系列方法或函数做封装,能够提高开发的效率,也方便后期维护

写插件前需要知道的预备知识

jQuery插件有哪几种类型?

  1. 封装对象方法的插件(对象级别)

    这类插件是最常见的一种,即将对象方法进行封装,然后通过选择器获取的jQuery对象进行操作。
    用法:$('#id').myPlugin()

  2. 封装全局函数的插件(类级别)

    即将独立的函数加到jquery命名空间下, 拓展jQuery类,典型例子$.ajax()
    用法:$.myPlugin()

jQuery插件中的闭包

常见的jQuery插件形式如下:

//为了更好的兼容性,开始有个分号
;(function ($) {
    /*你的插件代码*/
})(jQuery);

利用闭包的特性,避免内部变量影响全局空间,通过形参$将jQuery传递给匿名函数,在插件内部就可以使用$作为jQuery的别名。

jQuery插件的机制

//扩展第一种类型(即对象级别)的插件
jQuery.fn.extend()
//扩展第二种类型(即类级别)的插件
jQuery.extend()

extend()方法接受一个Object类型的参数,key值为函数名或方法名,value值为函数主体。

//给jQuery对象添加方法,就是对jQuery.prototype扩展,给jQuery类添加成员方法
$.fn.extend({ 
    getInputText: function(){ 
        $(this).click(function(){ 
            alert($(this).val()); 
        }); 
    } 
});
//$("#username").getInputText();

//给jQuery类扩展,相当于给jQuery添加静态方法
$.extend({
  add: function(a, b){return a + b;}
});
// $.add(1, 2); //return 3

除了可以扩展jQuery对象,$.extend(default, options)还可以扩展Object对象,用传入的参数options覆盖默认值default。

function myPlugin(options) {
    var defaults = {
        color: 'blue',
        width: '100'
    };
    options = $.extend(defaults, options);
}

//myPlugin({color: 'white'});
//myPlugin({color: 'white', width: '200'});
//myPlugin();

需要注意的问题

  • 插件名推荐命名为jquery.插件名.js,比如jquery.myPlugin.js

  • 插件内部this的指向为将要执行的jquery对象,而在其他包含callback的jQuery函数里,this指向原生DOM元素。

    (function($) {
        $.fn.m​​yPlugin = function () {
    
            //此处没有必要将this包在$号中如$(this),因为this已经是一个jQuery对象。
            //$(this)等同于 $($('#element'));
    
            this.fadeIn('normal', function () {
    
                //此处callback函数中this关键字代表一个DOM元素
    
            });
    
        };
    })(jQuery);
    
  • 用this.each对所有元素进行遍历,同时为了保持插件的链式调用,确保插件返回this关键字

    (function($) {
        $.fn.m​​yPlugin = function () {  
           return this.each(function () {
    
                //此处是你的插件代码
    
            });
    
        };
    })(jQuery);
    
  • 保护好默认参数

回顾上面讲$.extend(default, options)时举的例子

```
function myPlugin(options) {
    var defaults = {
        color: 'blue',
        width: '100'
    };
    options = $.extend(defaults, options);
}
```

这种写法不好,调用extend时会改变defaults的值,defaults作为插件默认值应维持原状,若后续想再使用默认值,会发现它已被用户传来的值所更改。
所以更好的写法是把一个新的空对象作为extend的第一个参数,接下来是defaults和options,那么所有值合并后保存到了这个空对象上,保护了默认值。

function myPlugin(options) {
    var defaults = {
        color: 'blue',
        width: '100'
    };
    options = $.extend({}, defaults, options);
}

动手编写一个jQuery插件

以分页插件作为练习,体会了上面的知识点,部分地方还有待优化

首先是HTML结构

//要插入页码的容器
<div id="pager"></div>
<p class="page-text"></p>

CSS结构

* {margin:0;padding: 0;}
ul {list-style: none;}

.page {height:40px;overflow: hidden;margin-top: 20px;}
.page li {display: inline-block;*display: inline;*zoom:1;border: 1px solid #CCC;background-color: #FFF;margin-right: 5px;padding: 5px 8px;cursor: pointer;}
.page li:hover {border:1px solid #1B4CA6;background-color: #BBD1F9;}
.page li.current {border:1px solid #1B4CA6;background-color: #BBD1F9;}
.page li.disable {border:1px solid #EEE;color:#999;cursor: auto;background-color: #FFF;}
.page-text {margin-top: 10px;}
.page-text strong {color: #78C6E2;margin-left: 3px;margin-right: 3px;}

js的结构

;(function($) {

    var defaults = {
        pagecurrent: 1,   //当前页码
        pagecount:1,      //页码总数
        first_text: '首页',  //首页按钮的文字可自定义
        prev_text: '上一页', //上一页按钮的文字可自定义
        next_text: '下一页', //下一页按钮的文字可自定义
        last_text: '尾页',  //尾页按钮的文字可自定义
        max_per_page: 10 //每屏最多显示多少个页码
    };

    $.fn.pager = function(options) {
        var options = $.extend({}, defaults, options);

        return this.each(function() {
            $(this).empty().append(renderPage(options));
        });
    }

    function renderPage(opts) {
        var pagecurrent = parseInt(opts.pagecurrent);
        var pagecount = parseInt(opts.pagecount);
        var btncallback = opts.btncallback;
        var max_per_page = parseInt(opts.max_per_page);
        var first_text = opts.first_text;
        var prev_text = opts.prev_text;
        var next_text = opts.next_text;
        var last_text = opts.last_text;
        //页码wrap
        var pageWrap = $('<ul class="page"></ul>');
        //添加第一页和上一页按钮
        pageWrap.append(renderBtn('first', first_text, pagecurrent, pagecount, btncallback))
        .append(renderBtn('prev',prev_text, pagecurrent, pagecount, btncallback));

        //控制一屏最多显示n条页码
        var startNum = 1;
        var endNum = max_per_page;
        var point = Math.ceil((endNum - startNum) / 2);

        if (pagecurrent > point) {
            startNum = pagecurrent - point;
            endNum = pagecurrent + point;
        }

        if (endNum > pagecount) {
            startNum = pagecount - max_per_page + 1;
            endNum = pagecount;
        }

        if (startNum < 1) {
            startNum = 1;
        }
        //渲染页码列表
        for (var pagenumber = startNum; pagenumber <= endNum; pagenumber++) {
            var pagebtn = $('<li>'+ pagenumber +'</li>');
            if (pagenumber == pagecurrent) {
                pagebtn.addClass('current');
            }
            else {
                pagebtn.click(function() {
                    btncallback(this.innerHTML);
                });
            }
            pageWrap.append(pagebtn);
        }

        //渲染下一页和尾页按钮
        pageWrap.append(renderBtn('next', next_text, pagecurrent, pagecount, btncallback))
        .append(renderBtn('last', last_text, pagecurrent, pagecount, btncallback));

        return pageWrap;
    }
    //首页,上一页,下一页,尾页按钮的方法
    function renderBtn(btntype, btntext, pagecurrent, pagecount, btncallback) {
        var button = $('<li>'+ btntext +'</li>');

        var destPage = 1;

        switch (btntype) {
            case 'first':
                destPage = 1;
                break;
            case 'prev':
                destPage = pagecurrent - 1;
                break;
            case 'next':
                destPage = pagecurrent + 1;
                break;
            case 'last':
                destPage = pagecount;
        }

        if (btntype == 'first' || btntype == 'prev') {
            if (pagecurrent <= 1) {
                button.addClass('disable');
            }
            else {
                button.click(function() {
                    btncallback(destPage);
                });
            }
        }
        else {
            if (pagecurrent >= pagecount) {
                button.addClass('disable');
            }
            else {
                button.click(function() {
                    btncallback(destPage);
                });
            }
        }

        return button;
    }

 })(jQuery);

调用

//Google的需要翻一下墙,你懂的--
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="jquery.pager.js" type="text/javascript"></script>


<script type="text/javascript">
        $(function(){
            $('#pager').pager({
                pagecurrent:1,
                pagecount:20,
                btncallback:pageClickCallback ,
                //first_text: 'first'
            });

        });
        pageClickCallback = function(pageclickednumber){
            $('#pager').pager({
                pagecurrent:pageclickednumber,
                pagecount:20,
                btncallback:PageClick,
                //first_text: 'first'
            });
            $('.page-text').html('当前是第<strong>'+pageclickednumber+'</strong>页');
        }
</script>


显示结果

pager分页

查看 demo


quanxi613
488 声望10 粉丝

剑复春秋听夜雨,风华袖底始忘言。


下一篇 »
SVG 初探

引用和评论

0 条评论