文档章节

自定义jQuery插件Step by Step

w
 wolf_su
发布于 2013/07/04 03:40
字数 3065
阅读 229
收藏 29

自定义jQuery插件Step by Step

1.1.1 摘要

随着前端和后端技术的分离,各大互联网公司对于Mobile First理念都是趋之若鹜的,为了解决网页在不同移动设备上的显示效果,其中一个解决方案就是Responsive Design;但我们今天不是介绍它,正由于前端开发已经十分重要了,所以我们将介绍如何使用jQuery自定义插件。

相信大家都使用过jQuery库,甚至自定义过一些常用的jQuery插件,如果没有学习过也无需担心,接下来我们将从一些简单的例子开始。

本文目录

1.1.2 正文

现在,jQuery库的功能已经很丰富了(The Write Less, Do More, JavaScript Library),但它也没有办法满足用户的所有需求,所以,它提供了一种机制:让用户给核心模块增加自定义的方法和额外的功能;通过这种机制,jQuery允许我们创建自定义的插件封装常用的方法,从而提高我们的开发效率。

控件模式

jQuery插件定义方式很简单,如果我们需要定义一个插件,只需给jQuery的$.fn对象添加一个新的函数属性就可以了,示例代码如下:

$.fn.myPluginName = function() { // Your plugin logic. };

现在,我们定义了一个函数myPluginName(),这样就创建了一个自定义插件了,但有一个问题我们要注意的是:由于美元符号(“$”)不仅仅只有jQuery库会使用到,其他Javascript库也可能使用到,假如其他库中“$”也有特别的含义,那么就会引起不必要冲突了。

其实,我们可以通过定义自执行的函数(IIFE),然后把jQuery对象作为参数传递给该自执行函数,通过建立“$”和jQuery的对应关系,这样“$”就不会在其执行范围中被其他库覆盖了。

(function($) {
    $.fn.myPluginName = function() { // your plugin logic };
})(jQuery);

大家看到这里,我们的插件通过闭包的方式封装起来了,这是为了确保我们使用“$”符号和其他JavaScript库之间不会冲突。

上面我们通过匿名函数的方式给myPluginName()方法赋值,我们也可以通过另外一种方法来创建自定义方法,那就是使用jQuery的extend()方法,它允许我们定义多个方法,而且语意更加简洁,示例代码如下:

(function($) {
    $.extend($.fn, {
        myplugin: function() { // your plugin logic }
    });
})(jQuery);

SignUp表单

现在,我们对jQuery自定义插件有了初步的了解,接下来,我们将通过具体的例子介绍自定义的jQuery插件的实现。

假设,我们需要定义一个表单校验的插件,也许有人会说:“jQuery已经提供了表单校验插件,我们真的有必要重做轮子吗?”,的确是这样,但这些插件功能十分丰富不利于刚开始的学习jQuery使用,我们更希望通过一个简单的例子介绍jQuery插件的定义。

我们有一个注册表单,它包含Name,Email,Password和Weibo等输入信息,现在,需要定义一个表单验证控件,验证用户的输入信息是否符合规则,表单的HTML代码如下:

<div class="validation-demo"> <!-- Start Sign Up Form --> <form action="#signup-form" id="Form1">
        <h2>Sign Up</h2>
        <fieldset>
            <div class="fieldgroup">
                <label for="name"> Name</label>
                <input type="text" name="name" validation="required"/>
            </div>
            <div class="fieldgroup">
                <label for="email"> Email</label>
                <input type="text" name="email" validation="email"/>
            </div>
            <div class="fieldgroup">
                <label for="password"> Password</label>
                <input type="text" name="password" validation="password"/>
            </div>
            <div class="fieldgroup">
                <label for="weibo"> Weibo</label>
                <input type="text" name="weibo" validation="url"/>
            </div>

            <div class="fieldgroup">
                <input type="submit" class="submit" value="Sign up">
            </div>
        </fieldset>

        <div class="fieldgroup">
            <p>Already registered? <a href="http://www.cnblogs.com/rush">Sign in</a>.</p>
        </div>
    </form> <!-- End Sign Up Form --> </div>

现在,我们需要验证Password长度,Email地址和Weibo地址的合法性,首先我们在input标签中添加validation属性标记该输入是否需要验证,接着我们设置validation的值:required,email,password和url。

validation0

图1注册表单

Validation对象

接下来,我们要创建一个Validation类型(类)用于验证用户输入信息,它包含4个方法分别用于验证Name、Email、Password和Url地址信息。

(function($) { // The validation function.
    // We adds validation rules for email, required field, password and url. var Validation = function() { var rules = {

            email: {
                check: function(value) { if (value) return isValidatedPattern(value, /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/); return true;
                },
                msg: "Please enter a valid e-mail address." },
            url: {
                check: function(value) { if (value) return isValidatedPattern(value, /^https?:\/\/(.+\.)+.{2,4}(\/.*)?$/); return true;
                },
                msg: "Please enter a valid URL." },
            password: {
                check: function(value) { if (value.length < 8 || value.length > 20) { return false;
                    } else { // Check the password strength enough. return isValidatedPattern(value, /(?=[A-Za-z0-9]{8,20})(?=.*[A-Za-z])(?=.*[0-9])[A-Za-z0-9]+/);
                    }
                },
                msg: "Your password must be at least 8 characters long." },
            required: {
                check: function(value) { if (value) return true; else
                        return false;
                },
                msg: "This field is required." }
        } var isValidatedPattern = function(value, pattern) { var regex = pattern; var match = regex.exec(value); return match;
        } // Returns a publish method, then the user can custom validation rule. return {

            addRule: function(name, rule) {

                rules[name] = rule;
            },
            getRule: function(name) { return rules[name];
            }
        }
    } //Creates instance of our object in the jQuery namespace. $.Validation = new Validation();
})(jQuery); // We're passing jQuery into the function
// so we can use $ without potential conflicts.

上面,我们定义了一个Validation类型,通过一个私有的数组rules保存了验证Name、Email、Password和Url对象;每个验证对象中都包含一个check()方法,如:email对象的check()方法,通过调用方法isValidatedPattern(),判断用户输入是否符合验证规则。

接着,我们返回公开的方法addRule()和getRule(),让用户可以通过addRule()方法增加自定义的验证方法。

我们在Validation类型中定义了公开的方法addRule(),通过该方法我们可以添加自定义的验证方法,而无需修改我们的插件代码。

接下来,让我们添加自定义的验证方法,具体代码如下:

// Adds custom rule. $.validation.addRule("CustomRule", {
    check: function(value) { if (value != "JK_Rush") { return false;
        } return true;
    },
    msg: "Must equal to the word JK_Rush." });

上面,我们通过addRule()方法添加了自定义的验证规则,由于addRule()方法是公开的,所以我们可以通过该方法往私有的rules数组添加自定义的验证规则。

表单对象

接下来,我们定义一个Form类型,它表示DOM中的表单实例。

// The Form type. var Form = function(form) { var fields = []; // Find the field has the validation attribute. form.find("[validation]").each(function() { var field = $(this); if (field.attr('validation') !== undefined) {
            fields.push(new Field(field));
        }
    }); this.fields = fields;
} // The Field type. var Field = function(field) { this.field = field; this.valid = false; //this.attach("change"); }

由于表单中有多个输入框,我们使用jQuery的each()方法来遍历表单中所有的输入框,查找到输入框中包含valiation属性的输入框,然后把field对象保存到fields数组中。

Javascript原型对象

ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

前面,我们创建一个类型Field用来表示表单中需要验证的输入框,那么Field实例对象必须有一个validate()方法,我们直接给Field对象添加validate()方法,具体实现如下:

var Field = function(field) { this.field = field; this.valid = false; //this.attach("change"); }

Field.validate = function() { // Your cdoe here. }

我们注意到每当创建一个Field对象时,都会分配给该对象一个独立的validate()方法,如果我们创建30个Field对象,那么就要给这30对象分配30次validate()方法,其实,validate()方法应该是共享的,也就是说每个Field对象都应该调用用一个validate()方法;这时我们可以使用原型链方式共享validate()方法。

接下来,让我们将在Field的原型属性(prototype)中添加validate()方法,具体实现如下:

// The prototype of Field type. Field.prototype = { // Public method. attach: function(event) { // The object refers to Field object. var obj = this; // When the field changed, then invoked the validate method. if (event == "change") {
            obj.field.bind("change", function() { return obj.validate();
            });
        } // When Key up, then invoked the validate method. if (event == "keyup") {
            obj.field.bind("keyup", function() { return obj.validate();
            });
        }
    }, // Public method. validate: function() { var obj = this,
                field = obj.field,
                errorClass = "errorlist",
                errorlist = $(document.createElement("ul")).addClass(errorClass), // We can splits the validation attribute with space.
        // Gets all validation types. types = field.attr("validation").split(" "), // Gets the fieldgroud object. container = field.parent(),
                errors = []; // If there is an errorlist already present
        // remove it before performing additional validation field.next(".errorlist").remove(); for (var type in types) { var rule = $.Validation.getRule(types[type]); // If invalid displays the error msg. if (!rule.check(field.val())) {

                container.addClass("error");
                errors.push(rule.msg);
            }
        } if (errors.length) { // Unbinds the keyup event added before. obj.field.unbind("keyup") // Attaches the keyup event. obj.attach("keyup");
            field.after(errorlist.empty()); // Displays the error msg. for (error in errors) {

                errorlist.append("<li>" + errors[error] + "</li>");
            }
            obj.valid = false;
        } else {
            errorlist.remove();
            container.removeClass("error");
            obj.valid = true;
        }
    }
}
validation2

图2 Field原型对象

我们在Field的原型中添加了两个方法,attach()方法用来绑定验证输入框的keyup和change事件,而validate()方法封装了调用具体校验方法。

现在,每个Field对象都可以调用继承于原型的attach()和validate()方法,假设表单中包含30个需要校验的输入,那么我们该如何遍历每个Field对象并且调用其validate()方法呢?

其实,Field对象都包含在Form对象中,由于我们在Form类型中定义了fields属性,它存储了包含validation属性field对象,所以我们可以通过访问Form的fields属性遍历每个field对象。

这里我们给Form的原型添加两个方法,validate()用来校验表单对象中的field,isValid()方法判断field对象是否符合验证规则,如果不符合规则就把焦点定在该输入框中。

// The prototype of Form. Form.prototype = { // Validates all the fields in the form object. validate: function() { for (field in this.fields) { this.fields[field].validate();
        }
    }, // If the field invaild, focus on it. isValid: function() { for (field in this.fields) { if (!this.fields[field].valid) { this.fields[field].field.focus(); return false;
            }
        } return true;
    }
}

validation3

图3 Form原型对象

插件使用

现在我们给Form对象添加了validate()和isValid()方法,接下来,我们将使用jQuery的扩展方法($.extend),使所有的jQuery对象都可以访问我们自定义的插件方法。

// Extends jQuery prototype with validation and validate methods. $.extend($.fn, {

    validation: function() { // Creates a Form instance. var validator = new Form($(this)); // Stores the Form instance in Key/Value collection. $.data($(this)[0], 'validator', validator); // Binds the submit event. $(this).bind("submit", function(e) {
            validator.validate(); if (!validator.isValid()) {
                e.preventDefault();
            }
        });
    }, // Checks the field is validated or not. validate: function() { var validator = $.data($(this)[0], 'validator');
        validator.validate(); return validator.isValid();

    }
});

我们在jQuery的扩展方法($.extend)中添加了两个方法,它们分别是validation()和 validate();validation()创建了一个Form对象,接着绑定了页面的submit事件,当页面方式提交时,验证表单输入是否正确。

现在,我们已经完成了自定义的jQuery插件了,那么接下来我们将使用该插件验证signupform。

我们在表单的HTML中引入jQuery库和自定义插件,具体代码如下:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.formvalidation.js"></script>

当然我们也把jQuery库下载到本地,然后引入到我们项目中。

接下来,我们在HTML页面中添加以下代码:

$(function() { // jQuery DOM ready function.

    // Get the form object. var signUpForm = $("#signup-form"); // Invokes the validation method. signUpForm.validation();
});

当DOM加载完毕后,就调用validation验证插件,当用户对页面进行提交或输入框的修改都会触发validate()方法。

1.1.3 总结

本文介绍了如何自定义jQuery插件,首先介绍了jQuery插件的定义方式,通过给jQuery的$.fn方法添加自定义方法来实现我们的插件。

接着,我们引入了表单验证控件例子来介绍jQuery插件的实现;我们在插件中定义了Form和Field类型,然后通过原型链方式共享Form和Field的方法,使得每个Form或Field对象实例可以调用其共享的方法。

希望大家在阅读本博文后,对jQuery插件的实现有进一步的了解。

参考

Demo下载

Jackson Huang

关于作者:

[作者]: JK_Rush从事.NET开发和热衷于开源高性能系统设计,通过博文交流和分享经验,欢迎转载,请保留原文地址,谢谢。
[出处]: http://www.cnblogs.com/rush/
[本文基于]: 署名-非商业性使用 3.0 许可协议发布,欢迎转载,演绎,但是必须保留本文的署名 JK_Rush (包含链接),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系 。

本文转载自:http://www.cnblogs.com/rush/archive/2012/10/28/2743957.html

w
粉丝 3
博文 75
码字总数 47499
作品 0
深圳
私信 提问
2016 年12月13个优秀的 jQuery 插件

1.Uppy Uppy是一个模块化文件上传插件,能够无缝集成任何框架。 支持从本地磁盘,Google云端硬盘,Dropbox,Instagram,远程URL,摄像机或其它位置提取文件,然后将其上传到最终目的地。 它具...

pe_mail2006
2016/12/07
4.4K
3
40+ 个最佳的 jQuery 旋转木马插件和教程

Carousel 也就是“旋转木马”广泛用于图片的展示,本文介绍超过40个 jQuery 的旋转木马插件和教材: 1. rCarousel 2. Agile Carousel 3. jCarousel 4. Tiny Carousel 5. Theatre 6. Step Ca...

小编辑
2011/08/23
7.3K
6
2013 年 12 月最好的 35+ 个 jQuery 插件

新的一年开始了,这里是我们 12 月份精心挑选出来最好的 jQuery 插件,希望能在众多的 jQuery 插件中找到你需要的。 1. Excolo-Slider Excolo Slider 是一款简单的 jQuery 滑动插件,支持响应...

oschina
2014/01/09
7.3K
25
前端开发者值得一看的 8 款实用 jQuery 插件

作为多年的WEB前端开发者来说,我用过非常多的jQuery插件,不是我懒,的确是因为jQuery插件使用太方便了,大大减少了我的工作时间。本文是我使用过的几款非常出色的jQuery插件,我想很有必要...

yykj
2012/11/20
11.1K
14
5 款最新的 jQuery 图片裁剪插件

这篇文章主要介绍最新的 5 款 jQuery 图片裁剪插件,可以帮助你轻松的实现你网站需要的图像裁剪功能。 Cropit Cropit 是一个 jQuery 插件,支持图像裁剪和缩放功能。Cropit 通过 FileReader...

oschina
2014/11/06
68.4K
16

没有更多内容

加载失败,请刷新页面

加载更多

CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
8
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
7
0
作为一个(IT)程序员!聊天没有话题?试试这十二种技巧

首先呢?我是一名程序员,经常性和同事没话题。 因为每天都会有自己的任务要做,程序员对于其他行业来说;是相对来说比较忙的。你会经常看到程序员在发呆、调试密密麻麻代码、红色报错发呆;...

小英子wep
今天
30
0
【SpringBoot】产生背景及简介

一、SpringBoot介绍 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程,该框架使用了特定的方式来进行配置,从而使开发人员不再需要...

zw965
今天
14
0
简述并发编程分为三个核心问题:分工、同步、互斥。

总的来说,并发编程可以总结为三个核心问题:分工、同步、互斥。 所谓分工指的是如何高效地拆解任务并分配给线程,而同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共...

dust8080
今天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部