月下博客

编写第一个jquery插件

jquery是web前端开发中最常用的一个js库,其跨平台的特性让开发人员省去了兼容的代码。就个人而言,jquery在dom操作和ajax两处的优势是其他库无可比拟的。

jquery的另外一个强大之处在于其丰富的拓展和插件。通过jquery提供的核心功能,开发者可以开发和发布自己的插件。目前前端的各种开发,几乎都有jquery插件在助力和简化开发过程。然而对于许多人而言,一直处于使用的阶段,没有介入开发的过程。

在项目中随处写下的jquery操作语句,会造成代码的维护困难和重复编码。为了解决这个问题,决定以学习开发插件。通过一个上午的学习,将第一个插件编写完毕。

jQuery插件开发方式主要有三种:

  1. 通过$.extend()来扩展jQuery
  2. 通过$.fn 向jQuery添加新的方
  3. 通过$.widget()应用jQuery UI的部件工厂方式创建

其中第一种主要用于拓展在jquery名字空间下的静态方法,例如内置的 $.log, $.error之类的方法。为了挖掘jquery在dom处理上的强大能力,一般的插件使用第二种方法。

第二种方法的写法同样很简单,直接往里添加代码即可:

$.fn.pluginName = {
    // your codes here
}

但是实际中为了不污染全局名字空间,经常将其放在闭包中:

;(function($, window){
    $.fn.pluginName = {
        // your codes here
    };
})(jQuery, window)

第一行开头的分号(;)是为了防止与其他代码压缩合并时,其未添加结尾分号造成的。通过闭包的形式,里面的任何变量都是私有的,从而防止了对全局空间的污染,也达到了提供接口的目的。

为了能够链式调用,要做的第一步是将作用的dom对象返回:

;(function($, window){
    $.fn.pluginName = function() {
        return this.each(function(){
             // your codes here
        })
    }
})(jQuery, window)

上述语句中,this指代选取的dom对象。由于选择的对象不一定只有一个,所以我们使用了jquery的.each方法。

目标是对表中的链接进行ajax请求,然后动态的将这一行删除。为了达到这个目的,可用如下代码:

;(function($, window){
    $.fn.delRow = function() {
        return this.each(function(){
             $(this).filter('a').on('click', function(){
                 var row = $(this).closest('tr');
                 var url = $(this).attr('href');
                 $.ajax({
                      url: url,
                      type: 'GET',
                      data: {'ajax': 1},
                      dataType: 'json'
                 }).done(response) {
                     if (!response.code) {
                          row.fadeOut().remove();
                     }
                     else {
                         window.alert(response.message);
                     }
                 }).fail(function(xhr, statusCode, error){
                     window.alert(error);
                 });

                 return false;
            })
        })
    }
})(jQuery, window)

插件的实现很简单:当用户点击表上的链接时,不触发默认的跳转操作,而是执行ajax请求,结果返回后将该行删除而无需刷新页面。

将这段js引入,调用的时候使用 $(selector).delRow()即可达到效果。

虽然目的达到了,但是问题还存在:插件里的请求方法等是写死的,如果想改变怎么办?所以希望插件的选项是能配置的。接下来给插件增加可选项。

;(function($, window) {
    $.extend({
        log: function(message) {
            if (window.console && window.console.log) {
                window.console.log(message);
            }
        }
    });

    $.fn.delRow = function(options) {
        var defaults = {
            'ajaxDelete': true,
            'type': 'POST',
            'requireConfirm': true,
            'confirmMessage': '你确认删除此条记录吗?',
            'warnMessageElem': $('#message')
        };

        var settings = $.extend({}, defaults, options);

        var handleClick = function() {
            var row = $(this).closest('tr');
            if (settings.requireConfirm) {
                if (!window.confirm(settings.confirmMessage)) {
                    return false;
                }
            }
            if (settings.ajaxDelete) {
                var url = $(this).attr('href');
                $.ajax({
                    url: url,
                    type: settings.type,
                    data: {'ajax': 1},
                    dataType: 'json',
                }).done(function(response) {
                    if (!response.code) {
                        row.fadeOut().remove();
                        settings.warnMessageElem.hide();
                    }
                    else {
                        var html = '<ul>';
                        for (x in response) {
                            html += '<li>' + response.message.x + '</li>';
                        }
                        html += '</ul>';
                        settings.warnMessageElem.show().html(html);
                    }
                }).fail(function(xhr, statusCode, error) {
                    $.log('code:' + statusCode);
                    $.log('message:' + error);
                }).always(function() {
                    $.log('handled!');
                });
                return false;
            }
            return true;
        }
        
        return this.each(function() {
            $(this).on('click', handleClick);
        });
    }
})(jQuery, window);

 

我们新增了如下选项:是否ajax请求,是否需要确认,确认信息和请求方法。调用的时候可以采取以下方式:

$(selector).delRow({
    'confirmMessage': '删除操作有危险,请您谨慎执行'
});

当用户点击表内链接的时候,则会弹出 “删除操作有危险,请您谨慎执行” 的确认框。

以上便是开发的第一个简单的插件。

 

参考:

  1. http://www.cnblogs.com/wayou/p/jquery_plugin_tutorial.html
  2. http://javascript.ruanyifeng.com/jquery/plugin.html
  3. http://www.cnblogs.com/cyStyle/archive/2013/05/18/jquery%E6%8F%92%E4%BB%B6%E8%AF%A6%E7%BB%86%E5%BC%80%E5%8F%91.html