【问题标题】:Wrap jQuery plugin with a function用函数包装 jQuery 插件
【发布时间】:2015-12-06 00:08:31
【问题描述】:

假设我有以下简单的插件:

(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'功能。

有可能吗?

【问题讨论】:

  • 这样做有什么意义?
  • @Vohuman 同意知道为什么会很有用 - 这可能是一项任务 - 或者他们想用一些前/后代码包装其他插件 - 或者他们不喜欢原始名称 -或者他们只是想因为他们不知道如何:goodreads.com/quotes/…
  • 你说得对,我应该解释更多,抱歉。这只是一个实验,我正在尝试学习如何安全地使用第三方插件。 @freedomn-m 提出了一些解释为什么更改或扩展插件命名空间可能有用的原因,我想采用这种方法的主要原因之一是防止第三方插件中的重复函数名称出现问题.通过对 Freedomn-m 解决方案的一些修改,我确实设法使其工作。

标签: javascript jquery function namespaces extend


【解决方案1】:

问题并不清楚,但我假设简单的插件“greenify”是第三方或其他“强制使用”插件,无论出于何种原因,您都无法更改。我们还假设它实际上是一个相当复杂的插件,为了这个问题而进行了简化。

这意味着

  • 你不能改变它
  • 您不能在包装器中复制整个插件

覆盖东西的常用方法是复制一份,然后让新版本做你想做的事,可能调用旧版本,例如:

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”并根据需要应用它来实现。

这里是完整的代码和解释 cmets:

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

【讨论】:

  • 所有其他答案在某些时候都是正确的,但您的解决方案正是我想要的。非常感谢。
【解决方案2】:

只要你的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();

编辑:如果重点是“禁用直接调用 greenify”,你为什么要首先扩展 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 定义为一个函数(而不是插件)并调用它。但是定义插件的目的是让它们可以被全局调用。

【讨论】:

  • 这也将允许直接调用greenify。关键是要问如何避免这种情况。
【解决方案3】:

我认为您在谈论方法链接,这是 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>

【讨论】:

    【解决方案4】:

    您肯定不想采用当前显示的方法,因为每次调用 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>

    【讨论】:

      【解决方案5】:

      如果你想创建自己的上下文,一种方法是返回一个带有一组函数的对象:

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

      Fiddle

      编辑:不过,作为一个警告,当您这样做时,您将在调用 .myFunction 后离开 jQuery 链接上下文,这在代码中可能非常令人困惑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多