jQuery插件的点点滴滴
说起jQuery插件,很多人的脑海种已经有了一定的雏形,仿佛感觉仅仅就是那样子,事实呢?当你看了Bootstrap.js,品读了slidesjs,观摩了jquery.cycle2.js,不禁发现,原来插件的世界千变万化,细微之处总是不容易让人发觉,世界那么大,那么我们就一起去看看它到底长什么样子?
工欲善其事必先利其器,如果你对于jQuery插件运用熟练的话,那么对已$.extend,你一定要去了解!,下面我们就先对$.extend来个剖析!先看看你对于$.extend的几种形式!
一、$.extend的用法
1 $.extend(dest,src1,src2,src3...)
2 $.extend({},src1,src2,src3...)
3 $.extend({name:function(){}})
4 $.fn.extend({name:function(){}})
5 $.extend({net:{}})
6 $.extend({boolean,dest,src1,src2,src3...})
$.extend(dest,src1,src2,src3...)
将src1,src2,src3...合并到dest中,请记住合并时,后面同名的属性会覆盖掉前面的属性,对于前面没有的属性,难就进行合并,如下:
<script type="text/javascript">
$(function() {
var obj = {
name: "yyh",
age: 26
},
obj1 = {
name: "yyh1",
age: 27
},
obj2 = {
name: "yyh2",
age: 27,
address:"chitu"
}
var mergeObj = $.extend(obj,obj1,obj2);
console.log(mergeObj)//{name: "yyh2", age: 27, address: "chitu"}
})
</script>
$.extend({},src1,src2,src3...)
这个和上面的是一样的,不同只是把dest={},把src1,src2,src3合并到一个空对象中,原理同上,不在赘述!
$.extend({name:function(){}})
看到这个东西,你可以这么认为,这是相当于$.extend(dest,src1) 中省略了dest后变成了$.extend(src1),这样子就相当于将该src合并到调用extend方法的对象中去,也就是将src合并到jquery的全局对象中去!举个例子,我们给jquery全局对象拓展一个是否支持CSS3的方法supportCSS3:
1 <script type="text/javascript">
2 $(function() {
3 $.extend({
4 supportCSS3: function() {
5 var body, i, style, transition, vendor;
6 body = document.body || document.documentElement;
7 style = body.style;
8 transition = "transition";
9 vendor = ["Moz", "Webkit", "Khtml", "O", "ms"];
10 transition = transition.charAt(0).toUpperCase() + transition.substr(1);
11 i = 0;
12 while (i < vendor.length) {
13 if (typeof style[vendor[i] + transition] === "string") {
14 return vendor[i];
15 }
16 i++;
17 }
18 return false;
19 }
20 })
21 if($.supportCSS3){
22 alert("该浏览器支持css33");
23 }
24 })
25 </script>
所以像$.get,$post,$.ajax就是jquery全局对象的方法!
$.fn.extend({name:function(){}})
和上面的$.extend相比,如果对于js的原型对象有了解,你肯定可以知道$.fn=jQuery.prototype,也就是说这种方式是把方法拓展到jquery对象的实例中,同样来个例子:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>demo1</title>
6 <script src="http://libs.baidu.com/jquery/1.10.0/jquery.js"></script>
7 </head>
8 <body>
9 <button id="btn1">点击</button>
10 <script type="text/javascript">
11 $(function() {
12 $.fn.extend({
13 say: function() {
14 alert("我是丑男孩");
15 return this;//为什么加this,jquery的链式写法,你懂的!
16 }
17 });
18 $("#btn1").on("click",function(){
19 $(this).say().hide();
20 })
21
22 })
23 </script>
24 </body>
25 </html>
$.extend({net:{}})
顾名思义,这个事在全局对象中扩展一个net命名空间,理解方式可以$.extend({name:function(){}}) 相似的。作用是干嘛?很简单假设团队有多个人,你担心推展到全局对象中会产生冲突,那么就自己独立建一个属于自己的空间,这样妈妈就在也不用担心儿子程序和别人冲突了!来个例子(如何来读取拓展的属性):
1 <script type="text/javascript">
2 $(function() {
3 $.extend({
4 yyh: {
5 age: 26,
6 address: "chitu",
7 supportCSS3: function() {
8 var body, i, style, transition, vendor;
9 body = document.body || document.documentElement;
10 style = body.style;
11 transition = "transition";
12 vendor = ["Moz", "Webkit", "Khtml", "O", "ms"];
13 transition = transition.charAt(0).toUpperCase() + transition.substr(1);
14 i = 0;
15 while (i < vendor.length) {
16 if (typeof style[vendor[i] + transition] === "string") {
17 return vendor[i];
18 }
19 i++;
20 }
21 return false;
22 }
23
24 }
25 });
26 //读取对应的属性
27 if($.yyh.supportCSS3){
28 alert("浏览器支持css3");
29 }
30 console.log($.yyh.age);
31 console.log($.yyh.address);
32 })
33 </script>
$.extend(boolean,dest,src1,src2,src3...)
这中方式,通过boolean,来决定是否深度拷贝!这种方式想必你在很多场合也见过了,boolean默认的是false,可以省略!至于为什么这样做呢?来个例子就豁然开朗了!
1 <script type="text/javascript">
2 $(function() {
3 var obj = {
4 name:{
5 nickname:"丑男孩",//外号
6 truename:"yyh",//真是姓名
7 },
8 age: 26
9 },
10 obj1 = {
11 name:{
12 nickname:"小男孩",//外号
13 truename:"yyh1",//真是姓名
14 },
15 age:25
16 },
17 obj2 = {
18 name:{
19 nickname:"老男孩",//外号
20 username:"uglyboy"
21 },
22 age: 27
23 }
24 var mergeObj1 = $.extend(true,obj,obj1,obj2);
25 //mergeObj1={name:{nickname: "老男孩",truename: "yyh1",username: "uglyboy",age: 27}}
26 var mergeObj2 = $.extend(false,obj,obj1,obj2);
27 //mergeObj2={name:{nickname: "老男孩",username: "uglyboy",age: 27}}
28 })
29 </script>
看完上面的例子的时候,你就知道如果false的时候,后面添加的对象的obj2中没有属性truename,合并后对象就不会有truename这个属性,所以写插件的时候会在里面看到如下:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>demo1</title>
6 <script src="http://libs.baidu.com/jquery/1.10.0/jquery.js"></script>
7 </head>
8
9 <body>
10 <script type="text/javascript">
11 ;(function($){
12 $.fn.Plugin=function(options){
13 //如果defaults是下面的形式,这里大可以不加boolean
14 var defaults={
15 property1:"value1",
16 property2:"value2",
17 property3:"value3",
18 method1:function(){},
19 method2:function(){},
20 };
21 var opt=$.extend(defaults,options);
22 }
23 })(jQuery)
24
25 ;(function($){
26 $.fn.Plugin=function(options){
27 //如果defaults是下面的形式,亲,记得加上boolean,不然传递参数可麻烦了!
28 var defaults={
29 property1:{
30 property11:"value11",
31 property12:"value12",
32 },
33 property2:{
34 property21:"value21",
35 property22:"value22",
36 },
37 property3:{
38 property31:"value31",
39 property32:"value32",
40 },
41 method1:function(){},
42 method2:function(){},
43 };
44
45 var opt=$.extend(true,defaults,options);
46 }
47 })(jQuery)
48
49 </script>
50 </body>
51
52 </html>
二、jquery插件的几种形式
1、传统的插件写法,defaut没有暴露出来供外部调用(这个应该我们写插件很常用的一种方式),下面是单个实例的时候
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="../css/reset.css">
<style type="text/css">
.undis {
display: none;
}
.tab-parent {
width: 400px;
margin: 50px auto;
border: 1px solid #e5e5e5;
}
.tab-hd {
height: 45px;
}
.tab-hd li {
padding: 15px 0;
width: 200px;
text-align: center;
float: left;
border-bottom: 1px solid #e5e5e5;
}
.tab-hd li.oncurr {
border-color: #f60;
color: #f60;
font-weight: bold;
}
.tab-bd {
padding: 20px;
min-height: 250px;
}
</style>
</head>
<body>
<div class="tab-parent" id="J_tab-parent">
<ul class="tab-hd">
<li class="tab-hd-item oncurr">选项卡1</li>
<li class="tab-hd-item">选项卡2</li>
</ul>
<div class="tab-bd">
<div class="tab-bd-item">选项卡1对应的内容</div>
<div class="tab-bd-item undis">选项卡2对应的内容</div>
</div>
</div>
<script type="text/javascript">
(function($) {
$.fn.Tab = function(options) {
var defaults = {
hdClass: '.tab-hd-item',
bdClass: '.tab-bd-item'
};
var opts = $.extend(defaults, options),
$hdItems=this.find(opts.hdClass),
$bdItems=this.find(opts.bdClass);
$hdItems.each(function(index, el) {
var $this=$(this);
$this.on("click",function(){
$this.addClass('oncurr').siblings().removeClass('oncurr');
$bdItems.eq(index).show().siblings().hide();
})
});
//如果想要支持链式写法,在这里请添加return this;
}
})(jQuery);
$(function() {
$("#J_tab-parent").Tab();
})
</script>
</body>
</html>
多个实例的时候
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="../css/reset.css">
<style type="text/css">
.undis {
display: none;
}
.tab-parent {
width: 400px;
margin: 50px auto;
border: 1px solid #e5e5e5;
}
.tab-hd {
height: 45px;
}
.tab-hd li {
padding: 15px 0;
width: 200px;
text-align: center;
float: left;
border-bottom: 1px solid #e5e5e5;
}
.tab-hd li.oncurr {
border-color: #f60;
color: #f60;
font-weight: bold;
}
.tab-bd {
padding: 20px;
min-height: 250px;
}
</style>
</head>
<body>
<div class="tab-parent" id="J_tab-parent">
<ul class="tab-hd">
<li class="tab-hd-item oncurr">选项卡1</li>
<li class="tab-hd-item">选项卡2</li>
</ul>
<div class="tab-bd">
<div class="tab-bd-item">选项卡1对应的内容</div>
<div class="tab-bd-item undis">选项卡2对应的内容</div>
</div>
</div>
<div class="tab-parent" id="J_tab-parent">
<ul class="tab-hd">
<li class="tab-hd-item oncurr">选项卡1</li>
<li class="tab-hd-item">选项卡2</li>
</ul>
<div class="tab-bd">
<div class="tab-bd-item">选项卡1对应的内容</div>
<div class="tab-bd-item undis">选项卡2对应的内容</div>
</div>
</div>
<script type="text/javascript">
(function($) {
$.fn.Tab = function(options) {
var defaults = {
hdClass: '.tab-hd-item',
bdClass: '.tab-bd-item'
};
var opts = $.extend(defaults, options);
return this.each(function(index, el) {
var $hdItems=$(this).find(opts.hdClass),
$bdItems=$(this).find(opts.bdClass);
$hdItems.each(function(index, el) {
var $this=$(this);
$this.on("click",function(){
$this.addClass('oncurr').siblings().removeClass('oncurr');
$bdItems.eq(index).show().siblings().hide();
})
});
});
}
})(jQuery);
$(function() {
$(".tab-parent").Tab();
})
</script>
</body>
</html>
2、default写成$.fn.default暴露出来供外部调用(这种方式的插件写法是很经常遇到的,比如jquery.cycle2.js),这个时候你应该会联想到$.fn.format在插件中的用法,这样的好处是可以让用户自定义自己的操作行为,而不用每次实例的时候都去传递同样的阐述,如下的例子:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="../css/reset.css">
<style type="text/css">
.undis {
display: none;
}
.tab-parent {
width: 400px;
margin: 50px auto;
border: 1px solid #e5e5e5;
}
.tab-hd {
height: 45px;
}
.tab-hd li {
padding: 15px 0;
width: 200px;
text-align: center;
float: left;
border-bottom: 1px solid #e5e5e5;
}
.tab-hd li.oncurr {
border-color: #f60;
color: #f60;
font-weight: bold;
}
.tab-bd {
padding: 20px;
min-height: 250px;
}
</style>
</head>
<body>
<div class="tab-parent" id="J_tab-parent">
<ul class="tab-hd">
<li class="tab-hd-item-1 oncurr">选项卡1</li>
<li class="tab-hd-item-1">选项卡2</li>
</ul>
<div class="tab-bd">
<div class="tab-bd-item-1">选项卡1对应的内容</div>
<div class="tab-bd-item-1 undis">选项卡2对应的内容</div>
</div>
</div>
<script type="text/javascript">
(function($) {
$.fn.Tab = function(options) {
var opts = $.extend($.fn.Tab.defaults, options);
return this.each(function(index, el) {
var $hdItems = $(this).find(opts.hdClass),
$bdItems = $(this).find(opts.bdClass);
$hdItems.each(function(index, el) {
var $this = $(this);
$this.on("click", function() {
$(this).html($.fn.Tab.format($(this).text()));
$this.addClass('oncurr').siblings().removeClass('oncurr');
$bdItems.eq(index).show().siblings().hide();
})
});
});
}
$.fn.Tab.defaults = {
hdClass: '.tab-hd-item',
bdClass: '.tab-bd-item'
};
$.fn.Tab.format = function(txt) {
return '<strong>' + txt + '</strong>';
};
})(jQuery);
$(function() {
$.fn.Tab.defaults = {
hdClass: '.tab-hd-item-1',
bdClass: '.tab-bd-item-1'
};
$(".tab-parent").Tab();
})
</script>
</body>
</html>
3、通过data的方式来实现jquery插件的写法(参考bootstrap.js,slidesjs)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script src="http://libs.baidu.com/jquery/1.10.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="../css/reset.css">
<style type="text/css">
.undis {
display: none;
}
.tab-parent {
width: 400px;
margin: 50px auto;
border: 1px solid #e5e5e5;
}
.tab-hd {
height: 45px;
}
.tab-hd li {
padding: 15px 0;
width: 200px;
text-align: center;
float: left;
border-bottom: 1px solid #e5e5e5;
}
.tab-hd li.oncurr {
border-color: #f60;
color: #f60;
font-weight: bold;
}
.tab-bd {
padding: 20px;
min-height: 250px;
}
</style>
</head>
<body>
<div class="tab-parent" id="J_tab-parent">
<ul class="tab-hd">
<li class="tab-hd-item oncurr">选项卡1</li>
<li class="tab-hd-item">选项卡2</li>
</ul>
<div class="tab-bd">
<div class="tab-bd-item">选项卡1对应的内容</div>
<div class="tab-bd-item undis">选项卡2对应的内容</div>
</div>
</div>
<script type="text/javascript">
;(function($, window, document, undefined) {
var pluginName = 'Tab',
defaults = {
hdClass: '.tab-hd-item',
bdClass: '.tab-bd-item'
};
function Plugin(element, options) {
this.element = element;
this.options = $.extend({}, defaults, options);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype.init = function() {
this.$hdItems = $(this.element).find(".tab-hd-item");
this.$bdItems = $(this.element).find(this.options.bdClass);
var _this = this;
this.$hdItems.each(function(index, el) {
var $this = $(this);
$this.on("click", function() {
$this.addClass('oncurr').siblings().removeClass('oncurr');
_this.$bdItems.eq(index).show().siblings().hide();
})
});
}
$.fn[pluginName] = function(options) {
return this.each(function() {
if (!$.data(this, 'plugin_' + pluginName)) {
return $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
})
}
})(jQuery, window, document);
$(function() {
$("#J_tab-parent").Tab()
})
</script>
</body>
</html>
基本的插件形式就这这三种,当然我们依然可以找到其他的方式的插件,比如私有方法的放置,还有像bootstrap.js的框架的细微的变形,万变不离其中,只要了解基本的方法,其他的都可以依葫芦画瓢!

浙公网安备 33010602011771号