jQuery插件开发

0.引子

jQuery是一个极其优秀和成功的框架,不仅本身使用极其简单,还提供了良好插件机制。本文将向您展示开发jQuery插件是件很简单的事,还会阐述模块化思想独立于任何语言之上。

1. 授人与渔,先授人与鱼

告诉你怎么开发jQuery插件不仅是本文的目的,让您明白背后的思想才是本文的价值所在。刚接触jQuery时,那种引入插件文件就拥有插件功能的机制,曾让我欣奇不已。现在我将它带给你,开始旅程吧。

2. 这是一个没有尽头的例子。

我们要开发一个插件,或者说我们要开发一个模块。什么是模块,不解释,跟着本文慢慢理解吧。
文件命名格式:jquery.模块名.js。

a. 告诉我这段文字反过来怎么读?
这是我要给你举的例子,一段文字‘’反转’的例子。清楚了没,我们需要开发一个插件,这个插件具有文字’反转’功能,我将称它是’文本’模块。为什么呢?先告诉你,我可能还要让这段文字加点颜色。所以它是‘’文本'模块。一般而言,模块有多个功能。

第1步:包含jquery文件并创建一个js文件 jquery.text.js。
<script type="text/javascript" src="/js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="/js/jquery.text.js"></script>

第2步:编写jquery.text.js文件。
当您引入jquery文件时,已经有个对象供您使用了,jQuery,整个插件将围绕这个对象变量玩转。先看下匿名函数。
(function(){}); 	 		// 最简单的匿名函数声明
(function(){})();	 		// 最简单的匿名函数调用
(function($){})(jQuery);	// 最简单插件实现

明白了没,为什么很多插件里,可以直接操作 $。用匿名函数主要是为了避免命名冲突,知道这点就行了。在实现之前,我们先看下如何调用。
jQuery(function(){	
	
	var s = $.text.reverse("请让我反过来");
	console.log(s);	// 输出 来过反我让请

});

直接给答案。

(function($){

$.extend($.text, {
    reverse: function(str) {
		var rv = '';
		for (var i = str.length-1; i >= 0; i--) {
			rv += str.substr(i, 1);
		}
	
		return rv;
    }
});

})(jQuery);

分析下:$.extend是什么?$.extend(对象,{ ... }),就将 { ... } 自动加到对象身上,即它就是扩展的用处。$是个对象,对象可以任意加属性,比如这里 $.text,至于为什么这样处理呢呢?很简单,体现模块。比如 $.text 体现文本模块,$.validate 体现验证模块,$.slide 体现轮播模块,等等。 到目前为止,你是不是很迷惑,我真正想表达什么,我已经向您展示模块化了。其实jQuery的插件是最好的理解模块化的方式了。可能你是个面向对象高手,你明白类,对象,继承,多态,抽象,设计模式这些东东,但是还有些你不知道的。

有没有觉得 $.text 很像类,reverse是它的一个静态方法?继续看吧。

b. 嘿,需求变了:一段文字,点击它时,让它文字反过来。
跟前面相似,在实现之前,我们先看下如何调用。
<div id='demo'>原来我是这样子的</div>

jQuery(function(){	
	
	$('#demo').reverse();

});

我喜欢先上答案。
(function($){

$.extend($.fn, {
    reverse: function() {
		$(this).click(function() {
			var newText = $.text.reverse($(this).text());
			$(this).text(newText);
		});

		return this;  // 这个返回是这样写吗?这是对的吗?是为了chain吗?
    }
});

$.extend($.text, {
    reverse: function(str) {
		var rv = '';
		for (var i = str.length-1; i >= 0; i--) {
			rv += str.substr(i, 1);
		}
	
		return rv;
    }
});

})(jQuery);

分析下:$.extend已经在上面说明过了。$.fn是什么呢?它表示任何jQuery元素对象,比如例子中的 $('#demo'),所以 $('#demo')这个对象扩展了一个方法 reverse,看它的实现细节,不难知道:点击时,将本身的文本反转。$.text.reverse上面说明过了。

3. 我准备制造麻烦了

我很无聊,经常会有一些可能别人认为没事找事做的想法。我现在有这样的需求:我不想点击时让它反转,我想初始化完就让它反转。聪明的你可能已经有方法应付了。
jQuery(function(){	
	
	$('#demo').reverse();
	$('#demo').click();     // 你真是人才,是我出的太蠢了?

});

c. 嘿,需求又变了:一段文字,点击它时,先弹出框(我准备反转了),然后让它文字反过来。
调用如下:
jQuery(function(){	
	
	$('#demo').reverse();

});

我太喜欢先上答案了。
(function($){

$.extend($.fn, {
    reverse: function() {
		$(this).click(function() {
			alert("我准备反转了");  // 加了一行弹出框,so easy

			var newText = $.text.reverse($(this).text());
			$(this).text(newText);
		});

		return this;  // 呆会你就知道,专家说的话不一定是对的。
    }
});

$.extend($.text, {
    reverse: function(str) {
		var rv = '';
		for (var i = str.length-1; i >= 0; i--) {
			rv += str.substr(i, 1);
		}
	
		return rv;
    }
});

})(jQuery);

这段不分析了,直接继续变化。

d. 该死的需求又变了:在上面的基础上,我想初始化完,文字就反转。
怎么调用呢?
jQuery(function(){	
	
	$('#demo').reverse();

	/* 不能click了,因为一点击,就弹出框了,怎么办呢?
	$('#demo').click();  
	*/

	// 好像可以这样,你觉得呢?你真的想把上面的实现代码copy过来吗?不是说好要重用的吗,哈哈。
	var newText = $.text.reverse($('#demo').text());
    $('#demo').text(newText);

});

不上答案,还真难怎么解释。继续上答案。
function($){

$.extend($.fn, {
    reverse: function() {
		var text = new $.text(this[0]);	 // 不用担心this[0],当作调用它的元素就行,后面会解释滴。

		return text;  // a. 返回一个对象了,不是this了,神奇。
    }
});

// b. 构造出一个对象。
$.text = function(div) {
	this.currentDiv = div;
	this.init();
};

$.extend($.text, {
	
	// c. 核心在这里。有点要说明的是,以下函数的 this 是指 text对象,已经不是那个操作元素了,它已经变成 this.currentDiv。
	prototype: {
		init: function() {
			(this.currentDiv).click(function() {
				alert("我准备反转了");

				this.reverse();
			});
		},
	
		reverse: function() {
			var newText = $.text.reverse($(this.currentDiv).text());
			$(this.currentDiv).text(newText);
		}
	},

    reverse: function(str) {
		var rv = '';
		for (var i = str.length-1; i >= 0; i--) {
			rv += str.substr(i, 1);
		}
	
		return rv;
    }
});

})(jQuery);

怎么调用呢?
jQuery(function(){	
	
	var text = $('#demo').reverse();
	text.reverse();

});

如果代码看不懂,请先看 打通JS任督二脉

4. 为什么这样设计?模块化是也

兑现开篇的承诺,这篇文章不仅让您知道怎么开发JQ插件,也会让您明白背后的思想。
摆在你面前的是一个项目,是一个系统工程,在您清楚需求之后,开始实现时(包括设计,编码...),您怎么入手呢?
模块化,不是类,也不是对象。怎么说呢?以这个例子说明。

需求:请开发一个插件(模块),提供服务、接口、API(都是同一个概念),具有反转的功能(可能还有其它功能)。

所以本身应该先立足于模块,也许你还做些初始化呢,模块定义好,比如是 $.text,这有个好处,概念清楚,命名空间也出来了。 其它语言的命名空间,包,这些其实也是想划分好模块而已。就像一个组件,已经摆在你面前了。
然后,这个模块要提供服务,或工具函数,比如例子中的 $.text.reverse(str)。这很有意思了,静态类方法,普通函数,其实都是工具而已。 模块也提供对象构造能力,比如 var text = new $.text(ele); 这是很重要的一个面向对象思想。对象的初始化由谁提供呢?我认为是模块。 很多人编程时,忽略了这一点,因为构造对象一般只有一条语句,比如 xxx = new Xxx(...); 其实不然的,也有很多有复杂构造的。像nginx里的 ngx_log_init,有兴趣的人可以看下,它放在 ngx_log.c 文件里。 所以是先有模块,再有对象的,对象的结构定义在模块文件里,模块也是个对象,是具有属性的,本例比较简单,没有涉及到这点。

5. 我隐藏了些什么:选项

写一些原理性的文章时,我经常会有意忽略一些细节,我认为读者明白原理之后,有些细节的应该自己去体会,这是一个很好的提升空间,我不能剥夺。 只是要插件,基本会提供选项参数,是的。这篇文章没有提到这点。大概给个答案: 
调用方式
jQuery(function(){	
	
	var text = $('#demo').reverse({ opt1: v1, opt2: v2, ...});
	text.reverse();

});

插件实现
(function($){

$.extend($.fn, {
    reverse: function(options) {
		var text = new $.text(options, this[0]);	 // 不用担心this[0],当作调用它的元素就行,后面会解释滴。

		return text;  // a. 返回一个对象了,不是this了,神奇。
    }
});

// b. 构造出一个对象。
$.text = function(options, div) {
	this.settings = $.extend(true, { }, $.text.defaults, options);
	this.currentDiv = div;
	this.init();
};

$.extend($.text, {
	defaults: {
        opt1: v1,
        play: v2,
		...
    },
	
	/* c. 核心在这里。有点要说明的是,以下函数的 this 是指 text对象,已经不是那个操作元素了,它已经变成 this.currentDiv。
	 * 以下函数可以使用选项:this.settings.opt1, ...
	 **/
	prototype: {
		init: function() {
			(this.currentDiv).click(function() {
				alert("我准备反转了");

				this.reverse();
			});
		},
	
		reverse: function() {
			var newText = $.text.reverse($(this.currentDiv).text());
			$(this.currentDiv).text(newText);
		}
	},

    reverse: function(str) {
		var rv = '';
		for (var i = str.length-1; i >= 0; i--) {
			rv += str.substr(i, 1);
		}
	
		return rv;
    }
});

})(jQuery);

5. 进一步学习

通用jQuery实现的轮播插件,已经开源,有兴趣的可以看下源码。
验证插件,作者是jQuery的核心成员,代码很有学习价值。

补充:jQuery插件没有通用的开发模式,你要根据实际情况灵活变通,比如 return 对象 好呢,还是 return this 呢?看具体情况。
模块命名以名词为主,功能以动词为主,比如验证插件里的,调用时 $('#testform').validate(...); 返回一个 validator 对象。 validate vs validator。








转载于:https://my.oschina.net/i33/blog/63031

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值