简体   繁体   English

用功能包装jQuery插件

[英]Wrap jQuery plugin with a function

Let's say I have following simple plugin: 假设我有以下简单的插件:

(function ( $ ) {
    $.fn.greenify = function() {
       this.css( "color", "green" );
       return this;
    };
}( jQuery ));

I don't want to make any changes to the plugin itself, but I would like to wrap with another function and extend its namespace as follow: 我不想对插件本身进行任何更改,但是我想包装另一个函数并扩展其命名空间,如下所示:

(function($) {
    $.fn.myFunction = function () {
        (function ($) {
            $.fn.greenify = function () {
                this.css("color", "green");
                return this;
            };
        }(jQuery));
    };
})(jQuery);

So I can call the plugin function like this: 所以我可以这样调用插件函数:

$(selector). myFunction().greenify();

Basically I want to disable calling 'greenify' function directly. 基本上我想禁用直接调用“ greenify”功能。

Is it possible? 可能吗?

It's not clear from the question, but I'm assuming the simple plugin "greenify" is a third-party or other "forced to use" plugin that you, for whatever reason, can't change. 这个问题尚不清楚,但是我假设简单的插件“ greenify”是第三方或其他“强制使用”插件,无论出于何种原因,您都无法更改。 Let's also assume that it's actually quite a complicated plugin and simplified for the sake of the question. 我们还假设它实际上是一个相当复杂的插件,并且出于问题的考虑而进行了简化。

This means 这意味着

  • you can't change it 你不能改变
  • you can't duplicate the entire plugin inside your wrapper 您不能在包装器中复制整个插件

The usual method for overwriting something is to take a copy, then make the new version do what you want, possibly calling the old version, eg: 覆盖某些内容的常用方法是制作副本,然后使新版本执行您想要的操作,可能会调用旧版本,例如:

var oldfoo = foo;
foo = function() { 
    alert("foo called");
    oldfoo();  // or oldfoo.apply(this) to be clearer
}

The same principle can be applied here, but instead make 'foo' (in the example above) null - to get rid of it, eg: 可以在此处应用相同的原理,但是可以使“ foo”(在上面的示例中)为null-摆脱它,例如:

var oldfoo = foo;
newfoo = function() { 
    alert("foo called");
    oldfoo();  // or oldfoo.apply(this) to be clearer
}
foo = null;

The complication is with jquery and wanting to keep the method chaining, which can be achieved by storing 'this' and applying it as desired. jQuery的复杂之处在于它希望保持方法的链接,这可以通过存储'this'并根据需要应用它来实现。

Here's the full code with explanation comments: 这是带有解释注释的完整代码:

// 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)
}

and a jsfiddle 和一个jsfiddle

If you want to create your own context, one way is to return an object with a set of functions: 如果要创建自己的上下文,一种方法是返回带有一组函数的对象:

(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);

Then you could call it using: 然后您可以使用以下命令调用它:

$(selector).myFunction().greenify();

Fiddle 小提琴

Edit: As a warning though, when you do this you are leaving the jQuery chaining context after calling .myFunction , which can be very confusing in code. 编辑:不过,作为警告,执行此操作时,您将在调用.myFunction后离开jQuery链接上下文,这可能会使代码非常混乱。

I think you're talking about method chaining which is the beauty of jQuery methods. 我认为您在谈论方法链接,这是jQuery方法的优点。 Define your new method as follows, but leave greenify() unchanged: 如下定义新方法,但保持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> 

Pretty sure so long as your myFunction returns this , that you should be able to chain whatever you want to it. 可以肯定的是,只要myFunction返回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();

EDIT: If the whole point is to "disable calling greenify directly", why would you extend jQuery in the first place? 编辑:如果要点是“禁用直接调用greenify”,那么为什么要首先扩展jQuery? 'greenify could be nested and triggered by passing an argument of some kind. 'greenify可以通过传递某种参数来嵌套和触发。 Something like: 就像是:

(function($) {
    $.fn.myFunction = function (options) {
        // Do some stuff

        if (options.greenify) {
            this.css("color", "green");
        }

        return this;
    };
})(jQuery);

$(selector).myFunction({greenify: true});

... or you could just define greenify as a function (instead of a plugin) and call it. ...或者您可以只将greenify定义为一个函数(而不是插件)并调用它。 But the point of defining plugins is so they can then be called globally. 但是定义插件的目的是使它们可以被全局调用。

You definitely don't want to take the current shown approach, because every time myFunction is called, it will also assign greenify. 您绝对不希望采用当前显示的方法,因为每次调用myFunction时,它也会分配绿色。 Simply take your myFunction plugin, assign a flag to the jQuery object that was constructed, and then check for that flag in 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> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM