用函数包装 jQuery 插件
Wrap jQuery plugin with a function
假设我有以下简单插件:
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
我不想对插件本身做任何更改,但我想用另一个函数包装并扩展其命名空间,如下所示:
(function($) {
$.fn.myFunction = function () {
(function ($) {
$.fn.greenify = function () {
this.css("color", "green");
return this;
};
}(jQuery));
};
})(jQuery);
所以我可以这样调用插件函数:
$(selector). myFunction().greenify();
基本上我想禁止直接调用‘greenify’函数。
可能吗?
如果您想创建自己的上下文,一种方法是 return 具有一组功能的对象:
(function($) {
$.fn.myFunction = function () {
// Cache jQuery object
var $this = this;
// Return interface that acts on jQuery object
return {
greenify: function () {
$this.css("color", "green");
return $this;
}
};
};
})(jQuery);
然后你可以调用它:
$(selector).myFunction().greenify();
编辑:但作为警告,当您这样做时,您将在调用 .myFunction
后离开 jQuery 链接上下文,这可能 非常 令人困惑在代码中。
我认为您在谈论方法链接,这是 jQuery 方法的优点。如下定义新方法,但保持 greenify()
不变:
(function($) {
$.fn.myFunction = function () {
return this.each(function() {
//Do stuff
});
};
})(jQuery);
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
(function($) {
$.fn.myFunction = function () {
return this.each(function() {
$(this).css({border:'1px solid black',textAlign:'center'});
});
};
})(jQuery);
$('.box').myFunction().greenify();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">COLOR CHANGE</div>
很确定,只要你的 myFunction
returns this
,你就应该能够链接任何你想要的东西。
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
(function($) {
$.fn.myFunction = function () {
// Do some stuff
return this;
};
})(jQuery);
$(selector).myFunction().greenify();
编辑:如果重点是"disable calling greenify directly",你为什么要首先扩展jQuery? 'greenify 可以通过传递某种参数来嵌套和触发。类似于:
(function($) {
$.fn.myFunction = function (options) {
// Do some stuff
if (options.greenify) {
this.css("color", "green");
}
return this;
};
})(jQuery);
$(selector).myFunction({greenify: true});
... 或者您可以将 greenify 定义为函数(而不是插件)并调用它。但是定义插件的目的是让它们可以全局调用。
你肯定不想采用当前显示的方法,因为每次调用 myFunction 时,它也会分配 greenify。只需使用您的 myFunction
插件,为构建的 jQuery 对象分配一个标志,然后在 greenify 中检查该标志。
(function($) {
$.fn.myFunction = function () {
this.greenMarker = true;
return this;
};
$.fn.greenify = function () {
if(!this.greenMarker) return this;
this.css("color", "green");
return this;
};
})(jQuery);
$('.f').greenify();
$('.g').myFunction().greenify();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="f">No Green</div>
<div class="g">Green Me</div>
问题并不清楚,但我假设简单插件 "greenify" 是第三方或其他 "forced to use" 插件,无论出于何种原因,您都无法更改。我们还假设它实际上是一个相当复杂的插件,为了问题的缘故进行了简化。
这意味着
- 你不能改变它
- 您不能在包装器中复制整个插件
通常覆盖的方法是复制一份,然后让新版本做你想做的,可能会调用旧版本,例如:
var oldfoo = foo;
foo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
这里可以应用相同的原则,但是将 'foo'(在上面的示例中)设置为 null - 以摆脱它,例如:
var oldfoo = foo;
newfoo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
foo = null;
复杂的是 jquery 并希望保持方法链接,这可以通过存储 'this' 并根据需要应用它来实现。
这是完整的代码和解释注释:
// The original plugin to be wrapped
(function ( $ ) {
$.fn.greenify = function() {
// changed to background-color for more impact (demo purposes)
this.css( "background-color", "lightgreen" );
return this;
};
}( jQuery ));
(function($) {
// allow this to be referred to later
// inside another loop where 'this' is something else
var me = this;
// take a copy of the original
// this stays inside the scope of (function($)) so can't be seen outside
me.original_greeny = $.fn.greenify;
// provide a wrapper
$.fn.myFunction = function () {
// the jquery elements for applying later
var $this = $(this)
// exported function
return {
greenify: function() {
// Call the original function with the jquery elements
// and return them for chaining
return me.original_greeny.apply($this)
}
};
};
})(jQuery);
// Now remove the original completely
(function ( $ ) {
$.fn.greenify = null;
}(jQuery));
// As desired, also demonstrating chaining still works
$("#a").myFunction().greenify().css("font-style", "italic")
// Confirm that the original has been removed
// gives error $(...).greenify is not a function
try {
$("#a").greenify()
} catch(e) {
$("#a").text("error on $().greenify: " + e)
}
和一个jsfiddle
假设我有以下简单插件:
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
我不想对插件本身做任何更改,但我想用另一个函数包装并扩展其命名空间,如下所示:
(function($) {
$.fn.myFunction = function () {
(function ($) {
$.fn.greenify = function () {
this.css("color", "green");
return this;
};
}(jQuery));
};
})(jQuery);
所以我可以这样调用插件函数:
$(selector). myFunction().greenify();
基本上我想禁止直接调用‘greenify’函数。
可能吗?
如果您想创建自己的上下文,一种方法是 return 具有一组功能的对象:
(function($) {
$.fn.myFunction = function () {
// Cache jQuery object
var $this = this;
// Return interface that acts on jQuery object
return {
greenify: function () {
$this.css("color", "green");
return $this;
}
};
};
})(jQuery);
然后你可以调用它:
$(selector).myFunction().greenify();
编辑:但作为警告,当您这样做时,您将在调用 .myFunction
后离开 jQuery 链接上下文,这可能 非常 令人困惑在代码中。
我认为您在谈论方法链接,这是 jQuery 方法的优点。如下定义新方法,但保持 greenify()
不变:
(function($) {
$.fn.myFunction = function () {
return this.each(function() {
//Do stuff
});
};
})(jQuery);
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
(function($) {
$.fn.myFunction = function () {
return this.each(function() {
$(this).css({border:'1px solid black',textAlign:'center'});
});
};
})(jQuery);
$('.box').myFunction().greenify();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">COLOR CHANGE</div>
很确定,只要你的 myFunction
returns this
,你就应该能够链接任何你想要的东西。
(function ( $ ) {
$.fn.greenify = function() {
this.css( "color", "green" );
return this;
};
}( jQuery ));
(function($) {
$.fn.myFunction = function () {
// Do some stuff
return this;
};
})(jQuery);
$(selector).myFunction().greenify();
编辑:如果重点是"disable calling greenify directly",你为什么要首先扩展jQuery? 'greenify 可以通过传递某种参数来嵌套和触发。类似于:
(function($) {
$.fn.myFunction = function (options) {
// Do some stuff
if (options.greenify) {
this.css("color", "green");
}
return this;
};
})(jQuery);
$(selector).myFunction({greenify: true});
... 或者您可以将 greenify 定义为函数(而不是插件)并调用它。但是定义插件的目的是让它们可以全局调用。
你肯定不想采用当前显示的方法,因为每次调用 myFunction 时,它也会分配 greenify。只需使用您的 myFunction
插件,为构建的 jQuery 对象分配一个标志,然后在 greenify 中检查该标志。
(function($) {
$.fn.myFunction = function () {
this.greenMarker = true;
return this;
};
$.fn.greenify = function () {
if(!this.greenMarker) return this;
this.css("color", "green");
return this;
};
})(jQuery);
$('.f').greenify();
$('.g').myFunction().greenify();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="f">No Green</div>
<div class="g">Green Me</div>
问题并不清楚,但我假设简单插件 "greenify" 是第三方或其他 "forced to use" 插件,无论出于何种原因,您都无法更改。我们还假设它实际上是一个相当复杂的插件,为了问题的缘故进行了简化。
这意味着
- 你不能改变它
- 您不能在包装器中复制整个插件
通常覆盖的方法是复制一份,然后让新版本做你想做的,可能会调用旧版本,例如:
var oldfoo = foo;
foo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
这里可以应用相同的原则,但是将 'foo'(在上面的示例中)设置为 null - 以摆脱它,例如:
var oldfoo = foo;
newfoo = function() {
alert("foo called");
oldfoo(); // or oldfoo.apply(this) to be clearer
}
foo = null;
复杂的是 jquery 并希望保持方法链接,这可以通过存储 'this' 并根据需要应用它来实现。
这是完整的代码和解释注释:
// The original plugin to be wrapped
(function ( $ ) {
$.fn.greenify = function() {
// changed to background-color for more impact (demo purposes)
this.css( "background-color", "lightgreen" );
return this;
};
}( jQuery ));
(function($) {
// allow this to be referred to later
// inside another loop where 'this' is something else
var me = this;
// take a copy of the original
// this stays inside the scope of (function($)) so can't be seen outside
me.original_greeny = $.fn.greenify;
// provide a wrapper
$.fn.myFunction = function () {
// the jquery elements for applying later
var $this = $(this)
// exported function
return {
greenify: function() {
// Call the original function with the jquery elements
// and return them for chaining
return me.original_greeny.apply($this)
}
};
};
})(jQuery);
// Now remove the original completely
(function ( $ ) {
$.fn.greenify = null;
}(jQuery));
// As desired, also demonstrating chaining still works
$("#a").myFunction().greenify().css("font-style", "italic")
// Confirm that the original has been removed
// gives error $(...).greenify is not a function
try {
$("#a").greenify()
} catch(e) {
$("#a").text("error on $().greenify: " + e)
}
和一个jsfiddle