如何使 jQuery 插件函数可调用以供独立使用,而不对集合进行操作

Posted

技术标签:

【中文标题】如何使 jQuery 插件函数可调用以供独立使用,而不对集合进行操作【英文标题】:How to make a jQuery plugin function callable for stand-alone use, that does not operate on a collection 【发布时间】:2012-09-07 07:57:44 【问题描述】:

我阅读了jquery documentation of plugin authoring 并且对此很熟悉。但是,给出的示例总是对一组先前匹配的元素进行操作。我想创建一个可以同时做这两个功能的函数:

// example usage of my to-be-created plugin function

// this is the way described in the docs, and I know how to do that
$("a").myFunction ()

// but I also want to be able to call the function without a collection:
$.myFunction ();

如果$.myFunction ()在没有要操作的集合的情况下被调用,它将创建自己的要匹配哪些元素的集合——一种初始化过程(但不一定只运行一次)。此外,$.myFunction ()应该保持可链接性。

我想要实现的伪代码:

// [...]
function myFunction (): 
    if (notCalledOnACollection) 
        // this should run when called via $.myFunction ()
        $elements = $("a.myClass");
    
    else 
        $elements = $(this);
    
    return $elements.each (function () 
        // do sth. here 
    );

我真的很想将所有函数实现/功能保留在一个函数定义中,而不是在 jQuery 对象内的两个不同位置有两个单独命名的函数或两个同名函数。

当然我可以添加一个参数myFunction (do_init) 来指示要执行if 语句的哪个分支,但这会使我的参数列表变得混乱(我想将这种方法用于多个插件,并且会有参数到myFunction (),为了简单起见,我在这里省略了)。

有什么好的建议吗?

【问题讨论】:

【参考方案1】:

只需在插件定义中添加另一个引用,您就可以轻松使用标准插件代码:

(function( $ ) 
    $.myPlugin = $.fn.myPlugin = function(myPluginArguments) 
        if(this.jquery)
            //"this" is a jquery collection, do jquery stuff with it
         else 
            //"this" is not a jquery collection
        
    ;

    $.fn.myPlugin.otherFunc = function() 
    ;
)( jQuery );

这里唯一的区别是$.myPlugin = 部分,它允许你直接调用你的插件而不运行jquery 的选择器函数。如果您决定需要其他函数或属性,可以将它们创建为插件的属性。

用法:

//using a selector (arguments optional)
$(".someClass").myPlugin();

//using the options variable - or whatever your arguments are
$.myPlugin(id: "someId");

//accessing your other functions/properties
$.myPlugin.otherFunc();

【讨论】:

我的解决方案存在严重问题。我已经在 jsfiddle 上复制了你的方法:jsfiddle.net/pnpbU 但是一旦我运行$.myPlugin (),所有测试的浏览器都会消耗 100% 的 CPU 并卡住(在 Linux 和 Windows 上使用 FF 进行测试,在 Mac 上使用 Safari 进行测试)。 我的机器上没有看到这个问题。而我现在正在恐龙身上。此外,jsfiddle 不应该用于性能测试,他们已经加载了一堆额外的东西。我也在本地进行了测试,也没有看到那里的问题。我真的怀疑你看到的和这段代码有什么关系。 你取消注释jsfiddle的js部分的行了吗?否则它不会运行!我现在在大学,可以使用一堆计算机,我可以在 3 台物理上不同的机器上重现 100% 的 CPU 消耗。使用jsfiddle.net/pnpbU(取消注释最后一行)并点击运行将阻止/结束 Fedora 17 上的脚本:Firefox 14.0.1、Chrome 22;视窗 7:火狐 14、IE9; OS X Lion:Safari 5、Firefox 14。所以它是明确可重现的。这个和jsfiddle没有关系,把那个脚本和jQuery 1.8.0一起复制运行,效果是一样的。 啊,现在我知道你哪里出错了。问题不在于我上面的代码,而是你添加到它的$(this).each。当你不发送选择器时,你不能以同样的方式使用this(没有选择器,没有集合,因此没有集合对象)。我已经更新了您的 fiddle,以展示带有和不带有选择器的 this 对象的区别。 啊,你是对的,我混淆了 if/else 分支。我现在做if (this.jQuery === undefined)  // build the collection /* do sth. with the collection */

以上是关于如何使 jQuery 插件函数可调用以供独立使用,而不对集合进行操作的主要内容,如果未能解决你的问题,请参考以下文章

我们如何使jquery终端屏幕可调?

如何使用 jQuery UI 使 datatables.js 的列可调整大小

jQuery写出可调控自定义的平滑滚动效果(锚点跳转动画)

如何使用 jQuery 使文本框可拖动?

如何使用纯 Javascript 使 HTML 元素可调整大小?

如何使用纯 Javascript 使 HTML 元素可调整大小?