旧驱动程序带您阅读jQuery插件开发过程。

jQuery插件开发模式

jQuery插件一般有三种方式开发:

通过jQuery扩展jQuery()
通过jQuery添加一个新的jQuery方法
由小部件()组件工厂方法创建,用于应用jQuery UI


第一种扩展()相对简单,一般很少能够独立开发复杂的插件。第三种是高级开发模式,本文没有介绍它,第二种是通用插件开发方式。本文着重于第二类。

插件开发

插件开发的第二种类型一般定义如下


美元。fn.pluginname =函数(){
您的代码在这里
}



插件开发中,我们一般采用面向对象的思维方式。

例如,定义一个对象


无功haorooms =功能(EL,OPT){
这个$元素= EL,
this.defaults = { {
颜色:',
字体:'12px,
textdecoration:不关
},
this.options(this.defaults,美元。延长= {},OPT)
}
对haorooms / /方法的定义
haorooms.prototype = { {
Changecss:函数(){
这element.css({美元回报。
颜色:this.options.color,
字体:this.options.fontsize,
textdecoration:this.options.textdecoration
});
}
}



美元。延长(this.defaults,选择{ } { })主要是创建一个新对象,保留对象的默认值。


美元。fn.myplugin =功能(选项){
/ /创建haorooms实体
无功haorooms =新haorooms(这个选项);
调用它的方法
Haorooms.changecss()返回;
}



调用此插件直接如下


$(函数(){())
$(A)。MyPlugin({
'色':' # 2c9929,
字体:'20px
});
})



上述开发方法存在的问题

有与上述方法开发一个严重的问题,这是定义一个全局haorooms,是不是该插件,兼容性好,在其他地方haorooms用例,你的代码是悲伤的!现在我们总结上面的代码,并使用一个自调用匿名函数(有时称为块级别范围或私有范围)来包装它,这样就不会发生。包括js插件的开发,同样的,我们使用一个自调用匿名函数来编写代码来包装,这样就可以了!包装方法如下:


(函数(){())

})




用上面的包裹,没问题。

但还有一个问题。当我们研究丹尼尔的代码时,我们经常看到它是为了避免不必要的错误,比如代码合并。

例如,我们随机定义一个函数:


haoroomsblog =函数(){ var

}
(函数(){())

})




因为haoroomsblog不添加这一功能背后一个分号,它使代码出错。为了避免这种情况,通常是书面的。


(函数(){())

})()




封装插件代码是一个简单的插件(js插件和jQuery插件都是一样的)。

还有一个问题。

包装插件


(函数(){())

})




基本上,它可以说是完美的。但是为了让你开发的插件应用更广泛、更良好的相容性,还要考虑一些特殊手法的运用,如插人,有些朋友为了避免jQuery和jQuery zeptojs冲突,前缀$,修改jQuery,修改文档的方法有些朋友会违约。为了得到你的插件的运行,这些东西已经修好,同样的方式,我们的做法是把代码如下:


函数($,窗口,文档,未定义){
我们的代码…
}(jQuery、窗口、文档);



你可以避免上述的一些事情!

一个很好的例子

接下来,我们有一个插件的基本级别:


(函数($){)
功能产生于(){ var =功能()
在这里运行的代码
}

var方法= {
函数(选项){
返回this.each(函数(){()
var $ = $(这个);
VAR设定this.data美元('pluginname);

如果(typeof(设置)= = 'undefined){

var默认值= {
属性名:价值,
onsomeevent:(功能){ }
}

设置(默认值,扩展名,},选项);

this.data美元('pluginname,设置);
{人}
设置(设置,扩展,{,},选项);
}

在这里运行的代码

});
},
销毁:函数(选项){
返回$(这个)。每个(函数()){
var $ = $(这个);

this.removedata美元('pluginname);
});
},
瓦迩:函数(选项){
VaR SomeValue = this.eq(0)Html();

返回SomeValue;
}
};

美元。fn.pluginname =函数(){
var方法=参数{ 0 };

如果(方法{方法}){
方法=方法{方法};
参数= array.prototype.slice.call(参数1);
否则如果}(typeof(法)'object| | {方法= =!)
方法methods.init;
{人}
美元。误差(表现+方法+不在jQuery。pluginname的存在);
返回此;
}

返回method.apply(这个参数);

}

}(jQuery);



您可能注意到,我提到的代码的结构与其他插件代码的结构非常不同,根据您的使用和需求,插件的开发也可能是多样化的,我的目标是澄清代码中的一些概念,这就足以让您找到一种方法来理解和开发jQuery插件。

现在,让我们剖析代码!

容器:即时执行功能

从根本上讲,每个插件的代码都包含在实时执行函数中,如下所示:


((arg1,arg2){函数
代码
})(arg1,arg2);



立即执行功能,顾名思义,是一个函数,是什么使它不同的是,它是包含在一对圆括号,它允许所有的代码运行在匿名函数的局部范围,这并不意味着DOM(全局变量)是屏蔽的功能,但对公共变量和对象的命名空间,无法访问里面的功能外,这是一个好的开始,所以当你声明你的变量和对象,你不必担心变量名和现有的代码之间的冲突。

现在,因为函数中的所有公共变量都不能访问,所以使用jQuery作为内部公共变量是一个问题,就像普通函数一样,即时函数也会根据引用引入到对象参数中,我们可以将jQuery对象传递给函数,如下所示:


(函数($){)

用于引用jQuery本地范围
}(jQuery);



我们进口一个公共变量jQuery为函数,立即执行,我们可以引用在函数部分(集装箱)。也就是说,我们称之为容器作为一个函数,这个函数的参数是与jQuery。因为我们指的是jQuery是引入一个共同的变量,而不是短期美元,所以我们可以与原型库兼容。如果你不使用原型或其他图书馆做速记,你不会如果你不做任何区别,但知道这种用法仍然是一件好事。

插件:函数

一个jQuery插件基本上是我们成了一个巨大的功能在jQuery命名空间,当然,我们可以很容易地使用jQuery。pluginname =函数来实现我们的目标,但如果我们做我们的插件代码是不受保护的state.jquery.fn暴露是一种速记jquery.prototype,意味着当我们让我们的插件通过jQuery命名空间它只能被写入(不可修改),它可以为你做的事实什么它允许您正确地组织自己的代码,并了解如何保护代码不受运行时不需要的更改的影响,最好说的是这是一个很好的实践!

通过一个插件,我们得到了一个基本的jQuery函数:


(函数($){)

美元。fn.pluginname =功能(选项){

在这里运行的代码

返回此;
}

}(jQuery);



在上面的代码中的函数可以被$(' #元),PluginName()为其他jQuery函数。注意,我说这句话的回报。代码块生成链的作用调用返回原始元素的引用(中),这是一个jQuery对象包。你也应该注意到,这是在这个特定的范围一个jQuery对象,相当于$(' #元素)。

根据返回的对象,我们可以得出这样的结论:在上面的代码中,使用美元的影响(#元),PluginName()是使用$相同(#元),你立即执行功能的范围,也没有必要把这一个jQuery对象的方式$(这),因为这本身已经是封装jQuery对象。

多元素:理解的嘶嘶声

使用jQuery的选择器引擎叫啸,和啸可以为你提供多元素操作功能(例如,所有相同的元素的类名)。这是一个jQuery的许多优良特性,但这是你需要考虑的一个plug-in.even发展过程中如果你不准备好为您提供多元支持插件,它仍然是准备好的实践。

在这里,我添加了一小段代码,让您的插件代码可以为多元素集合中的每个元素分别工作:


函数($){

/ /添加插件代码fn命名空间使用jQuery的保护,pluginname作为一个插件的函数名称
美元。fn.pluginname =功能(选项){

返回此函数(返回值为此),以便调用链。
返回this.each(函数(){()

在这里运行代码,可以通过这个获得单个元素
例如:$(这个)(/ show);
var $ = $(这个);

});

}

}(jQuery);



在上面的例子中的代码,我没有使用每()来对我选择的每一个元素运行代码。在调用的函数的每个局部范围(),你可以查阅每一个处理单元的,也就是说,你可以参考它的jQuery对象的方式这个地方的范围,我使用这个变量来存储美元的jQuery对象而不是使用这个调用函数时。这是一个很好的实践,当然,这并不总是必要的,但是我已经把它包含在我的代码中了,同样重要的是要注意,我们将为每一个方法使用每个(),这样我们就可以返回我们需要的值,而不是返回一个jQuery对象。

下面的例子是,如果我们的插件支持一个瓦尔方法,它可以返回我们需要的值:


$(#元),PluginName('val);
我们需要返回值,而不是jQuery对象。



功能:公共和私有方法

在某些情况下,基本功能可能工作得很好,但是稍微复杂一点的插件需要提供各种方法和私有函数。

下面的代码定义了一个JSON对象,它存储公共方法,并演示如何使用插件中的main函数来确定调用哪种方法以及如何使该方法在选择器的每个元素上工作。


(函数($){)

在我们的插件容器中,创建一个公共变量来构建私有方法
功能产生于(){ var =功能()
代码
}

通过存储创建一个文本对象,我们需要常用的方法
var方法= {
字面对象中每个个体的定义方法
init:函数(){

为了从主函数中获得更好的灵活性,并在每个选择器中输入每个元素以执行代码的方法
返回this.each(函数(){()
为每个单独的元素创建jQuery对象
var $ = $(这个);

执行代码
例如:(功能产生于) / /;
});
},
销毁:函数(){
对于选择器的每个元素都有执行方法
返回this.each(函数(){()
执行代码
});
}
};

美元。fn.pluginname =函数(){
不幸的是,如果我们使用函数(方法){实现,我们将破坏一切。
var方法=参数{ 0 };

是否存在测试方法
如果(方法{方法}){

如果存在该解决方案,则存储以供使用
注意:我要做的是让每个(下)使用起来更加容易。
方法=方法{方法};

如果该方法不存在,则检查对象是对象(对象JSON)或不引入方法方法。
否则如果}(typeof(法)'object| | {方法= =!)

如果我们传递对象是一个参数,或者没有参数,init方法将被调用。
方法methods.init;
{人}

方法不存在或不提供参数、错误。需要调用的方法没有正确调用。
美元。误差(表现+方法+不在jQuery。pluginname的存在);
返回此;
}

我们已经选择了方法调用
请再次注意我们将如何从每个方法到每一个方法
返回method.call(本);

}

}(jQuery);



请注意,我认为在一个功能功能产生于一个全局变量,考虑到插件容器运行的所有代码,这种方法是可以接受的,因为它只能在plug-ins.in主要功能范围的插件,我检查方法中传入的参数是针对存在。如果方法不对存在或输入对象,init方法将运行。最后,如果传入的参数不是一个对象,但一个不存在的方法,我们将报告一个错误信息。

要注意同样的事情是如何使用this.each()在每一个方法,我们称method.call当(本)的主要功能,这在这里实际上是一个jQuery对象,引入各法为本。所以我们的方法即时的范围,它已经是一个jQuery对象的。只有在调用函数时每(),这是我们把这一个jQuery对象的必要。

下面是一些用法示例:


*
请注意,这些示例可以在当前的插件代码中正确运行,并不是所有的插件都使用相同的代码结构。
* /
每类 / / 。类名元件执行init方法
$('。类名)。PluginName();
$(方法),PluginName('init);
$(方法),PluginName('init,{ }){ }; / /传入的对象作为函数参数的初始化方法
$(方法),PluginName({ } { }); / /传入的对象作为函数参数的初始化方法

每个类实现 /破坏。类名元
$(方法),PluginName('destroy);
$(方法),PluginName('destroy,{ }){ }; / /输入对象的销毁方法作为函数参数

所有代码都可以正常运行。
$(方法),PluginName('init ','argument1 ','argument2 '); / / 参数1和2参数,

使用错误
$(方法),PluginName('nonexistantmethod);
$(方法),PluginName('nonexistantmethod,{ });
$(方法),PluginName('argument 1 '); / /将尝试调用参数1的方法
$(方法),PluginName('argument 1',2''argument); / /将尝试调用的说法1
$(方法),PluginName('privatefunction '); / / 'privatefunction'is不是一种方法




在上面的例子中多次出现的参数{ },,在这一部分中,上面的代码可以正常运行,但参数不会被传递到方法。继续阅读下一节,你将知道如何传递参数的方法,建立了许多插件:插件来参数支持参数的输入,如配置参数和回调函数,你可以为方法提供信息通过JS关键价值的对象或函数的参数。如果你的方法支持一个或两个以上的参数,有比没有更合适的方式传入的对象参数。


(函数($){)
var方法= {
函数(选项){

每个元素中的执行方法
返回this.each(函数(){()
var $ = $(这个);

创建默认对象
var默认值= {
属性名:价值,
onsomeevent:(功能){ }
}

使用扩展方法从选项和默认对象构造一个设置对象
var设置(默认值、扩展名、选项);

执行代码

});
}
};

美元。fn.pluginname =函数(){
var方法=参数{ 0 };

如果(方法{方法}){
方法=方法{方法};

我们的方法作为参数传递,将其从参数列表中删除,因为它不需要调用方法。
参数= array.prototype.slice.call(参数1);
否则如果}(typeof(法)'object| | {方法= =!)
方法methods.init;
{人}
美元。误差(表现+方法+不在jQuery。pluginname的存在);
返回此;
}

使用应用程序方法将我们命名为参数
返回method.apply(这个参数);

}

}(jQuery);



如上图所示,一个选项参数添加到方法和参数添加到主函数。如果一个方法被声明,该方法的参数将被删除从参数列表之前的参数被传递到方法。我将()而不是叫(),用()基本上是相同的工作,叫(),但不同的是,它允许参数的介绍。从这个结构还允许多个参数,如果你愿意的话,你也可以修改你的方法如参数列表:init(arg1,arg2):功能{ }。



如果您使用js对象作为参数,您可能需要定义一个默认对象。一旦声明了默认对象,您可以使用扩展名将参数对象和默认对象中的值合并为一个新的参数对象(在我们的例子中,设置)。

下面是一些例子来演示上面的逻辑:


var选项{ {
CustomParameter:测试1,
属性名:测试2
}

var默认值= {
属性名:测试3,
onsomeevent:测试4
}

var设置(默认值、扩展名、选项);
*
设置= {
属性名:测试2,
onsomeevent:测试4,
CustomParameter:测试1
}
* /



保存设置:添加持久性数据

有时您希望保存插件中的设置和信息,并且可以使用jQuery中的数据()函数,使用起来非常简单。它将尝试获取与元素相关的数据。如果数据不存在,则会创建相应的数据和添加元素。一旦你使用的数据(信息)的添加元素,让你想起在元素上移除存放的数据不再需要的数据,删除相应的数据。


(函数($){)
功能产生于(){ var =功能()
执行代码
}

var方法= {
函数(选项){

每个元素中的执行方法
返回this.each(函数(){()
var $ = $(这个);

尝试设置,如果没有设置,它将返回未定义。
VAR设定this.data美元('pluginname);

如果设置失败,则根据选项和默认值创建它。
如果(typeof(设置)= = 'undefined){

var默认值= {
属性名:价值,
onsomeevent:(功能){ }
}

设置(默认值,扩展名,},选项);

保存新创建的设置
this.data美元('pluginname,设置);
{人}
如果我们得到了设置,然后将其与选项合并(没有必要,您可以选择不这样做)
设置(设置,扩展,{,},选项);

如果您每次都想保存选项,可以添加以下代码:
/ / this.data美元('pluginname,设置);
}

执行代码

});
},
销毁:函数(选项){
在每个元素上执行代码
返回$(这个)。每个(函数()){
var $ = $(这个);

执行代码

删除相关数据中的元素
this.removedata美元('pluginname);
});
},
瓦迩:函数(选项){
下面的代码是:(0)获取选择器中的第一个元素,返回值时得到HTML或它的内容。
VaR SomeValue = this.eq(0)Html();

返回值
返回SomeValue;
}
};

美元。fn.pluginname =函数(){
var方法=参数{ 0 };

如果(方法{方法}){
方法=方法{方法};
参数= array.prototype.slice.call(参数1);
否则如果}(typeof(法)'object| | {方法= =!)
方法methods.init;
{人}
美元。误差(表现+方法+不在jQuery。pluginname的存在);
返回此;
}

返回method.apply(这个参数);

}

}(jQuery);



在上面的代码中,我检查了元素的数据是否存在。如果数据不存在,选项和默认值将被合并,构建到一个新的设置中,然后用数据()存储在元素中。