Tim*_*ijk 9 javascript jquery plugins design-patterns
我一直在开发jQuery插件已有一段时间了,我想我现在知道如何设计好一个.然而,有一个问题一直困扰着我,那就是如何以强大而优雅的方式处理私有功能.
我的插件通常看起来像这样:
(function($) {
$.fn.myplugin = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'green');
...
};
$.fn.mypluginAnotherPublicMethod = function(...) {
...
// some shared functionality, for example:
this.css('background-color', 'red');
...
};
}(jQuery));
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:如何巧妙地干掉共享功能?一个明显的解决方案是将它放在插件命名空间中的函数中:
var fill = function($obj, color) {
$obj.css('background-color', color);
};
Run Code Online (Sandbox Code Playgroud)
虽然这个解决方案很有效且命名很好,但我真的不喜欢它.原因很简单:我必须传递jQuery对象.即我必须这样称呼它:fill(this, 'red');,虽然我想这样称呼它:this.fill('red');
当然,我们可以达到这个结果简单地把fill成jQuery.fn.但这感觉非常不舒服.想象一下,在此基础上的方法和每个插件把这些"私人"功能,五成jQuery函数命名空间开发10个插件.它最终陷入了混乱.我们可以通过在前面的每一个与他们属于插件的名称,这些功能减少,但并没有真正使其更具吸引力.这些功能应该是私有的插件,所以我们不希望他们在所有的(直接至少不会)暴露于外界.
所以我的问题是:你们中是否有人有关于如何充分利用两个世界的建议.那是; 插件代码能够调用的方式类似"私人"的插件功能this.fill('red')(或者this.myplugin.fill('red')甚至this.myplugin().fill('red')等),同时防止jQuery函数命名空间的污染.当然它应该是轻量级的,因为这些私有函数可能会被频繁调用.
更新:感谢您的建议.
我特别喜欢David的定义一个包含'private'函数并包装jQuery对象的对象类型的想法.唯一的问题是它仍然不允许我链接"私人"和"公共"功能.这是想要this.fill('red')开始使用语法的重要原因.
我最终找到了一个我认为不是非常优雅的解决方案,但却吸引了"两全其美"的原因:
$.fn.chain = function(func) {
return func.apply(this, Array.prototype.slice.call(arguments, 1));
};
Run Code Online (Sandbox Code Playgroud)
这允许构造如:
this.
find('.acertainclass').
chain(fill, 'red').
click(function() {
alert("I'm red");
});
Run Code Online (Sandbox Code Playgroud)
我在其他地方交叉发布了我的问题,这也收集了一些有趣的回答:
Dav*_*ing 11
有一两件事第一:如果你想打电话给像this.fill('red');这里这个是jQuery的实例,你必须扩展jQuery的原型,让fill()"公开".jQuery提供了使用所谓的"插件"来扩展它的原型的指南,这些插件可以使用$.fn.fill,它是相同的jQuery.prototype.fill.
在jQuery回调中,这通常是对HTML元素的引用,并且您无法向那些(还)添加原型.这就是为什么jQuery包装元素并返回可以轻松扩展的jQuery实例的原因之一.
使用(function(){})();语法,您可以动态创建和执行"私有"javascript,并在完成后消失.使用这种技术,您可以创建自己的类jQuery语法,将jQuery包装到您自己的私有可链接对象中.
(function(){
var P = function(elem) {
return new Private(elem);
};
var Private = function(elem) {
this.elem = jQuery(elem);
}
Private.prototype = {
elem: null,
fill: function(col) {
this.elem.css('background',col);
return this;
},
color: function(col) {
this.elem.css('color', col);
return this;
}
}
$.fn.myplugin = function() {
P(this).fill('red');
};
$.fn.myotherplugin = function() {
P(this).fill('yellow').color('green');
};
})();
$('.foo').myplugin();
$('.bar').myotherplugin();
console.log(typeof P === 'undefined') // should print 'true'
Run Code Online (Sandbox Code Playgroud)
这样,P代表您自己的"私有"功能工具箱.它们将无法在代码中的任何其他位置或jQuery命名空间中使用,除非您将它们附加到某处.你可以在Private对象中添加任意数量的方法,只要你返回它,你也可以像我在示例中那样链接它们jQuery样式.
怎么样(在插件的范围内):
var fill = function ()
{
(function (color)
{
this.css ('backgrorund-color', color);
//.. your stuff here ...
}).apply (this, arguments);
}
$.fn.myplugin = function ()
{
fill ('green');
}
Run Code Online (Sandbox Code Playgroud)
这样, fill 将保留您所在的 jQuery 上下文,并且仍然是您的插件私有的
修正:上面的范围界定不正确,请尝试以下操作:
var fill = function (color)
{
if (!$this) return; // break if not within correct context
$this.css ('backgrorund-color', color);
//.. your stuff here ...
}
$.fn.myplugin = function ()
{
var $this = $(this); // local ref to current context
fill ('green');
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7623 次 |
| 最近记录: |