我们知道jQ插件,是通过$.fn来进行拓展的,但是为什么这样能拓展,可能就没多少人知道了。其实我们简单测试一下就明白了:
console.log($.fn);
输出的结果发现全是jQ的api,这就让人想到了对象的原型。jQ应该也有原型吧,$.fn跟原型究竟是什么关系?再接着测试:
console.log($.fn===$.prototype);
结果为:true
这就让人恍然大悟,所谓的插件原来就是给jq的原型添加功能函数。
比如现在我们有两个div,我们要想封装一个插件,实现在某个div里面插入几行ul li 并赋值:
<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
首先给jQ对象添加addList方法:
$.fn.addList = function(data){
var $ul = $("<ul></ul>");
for(i =0 ;i<data.length;i++){
var $li = $("<li>"+data[i]+"</li>");
$li.appendTo($ul) ;
}
$ul.appendTo(this);
}
$("#box1").addList(["1","2","3","4"]);
这里我们实现了一个给代理对象添加ul和li以及内容的功能,然后我需要将这个功能封装成一个插件,当用户引入这个插件就能使用该方法。
封装插件时我们不能直接把这段代码直接复制过去,因为这里这些代码全是开放的,全是在window作用域,很有可能有其他跟插件同名的函数污染插件。
(function(root,factory,plug){
root[plug] = factory(root.jQuery,plug);
})(window,function($,plug){
$.fn[plug] = function(data){
var $ul = $("<ul></ul>");
for(i =0 ;i<data.length;i++){
var $li = $("<li>"+data[i]+"</li>");
$li.appendTo($ul) ;
}
$ul.appendTo(this);
}
},"addList")
我们将这插件直接一调用就执行。函数后面加括号表示直接执行。(如果方法是动态的,就用[]访问,静态的就用点访问)
root代表环境,目前是window环境,别人用这插件,不一定是在window环境下。
factory表示你这个插件功能函数
plug表示插件名称
由于是JQ插件,所以要传入当前环境下引入的jQuery
不过到了这一步,并不代表这个插件完整。因为用户不一定只传data参数,可能还有其他参数,如果没有传参数,我们需要给一个默认值,不能让插件报错。
设置默认值:
var __def__ = {
data:0,
name:"Stella",
age:18
}
设置要执行的功能:
var __prop__ = {
_init : function(){
var $ul = $("<ul></ul>");
for(var i=0;i<this.data.length;i++){
$ul.append($("<li>"+this.data[i]+"</li>"));
}
this.append($ul);
}
};
紧接着我们还要实现,有传入值时用传入值,没有时用默认值,这里就要用到extend:
$.fn[plug] = function(options){
$.extend(this,__def__,options,__prop__);//将后面三个对象的方法属性以及值合并后赋给this对象。
this._init();//this对象拥有了_init方法,进行执行
}
调用插件有这两种方式:
$("#box1").dnList({
data : ["1","2","3","4"],
name:"abc"
});
new dnList({
dom:document.getElementById("box1"),
data : ["a","w","d","e","f"],
age:19
});
为了做到第二种方式也能实现,不报错,达到两者兼容。这时还需要加一个输出函数
return function(options){
var dom = options.dom;
$(dom)[plug].call($(dom),options);执行插件功能函数,将this指向$(dom)这个代理对象,并传入参数。
}
最终的插件:
调用:
$("#box1").addList({
data:[1,2,3,4],
name:"Ivan",
age:20
});
new addList({
dom:document.getElementById("box2"),
data:[5,6,7,8],
name:"Stella",
})
显示结果:
本文为头条号作者发布,不代表今日头条立场。