草庐IT

javascript - 用于处理私有(private)函数的 jQuery 插件设计模式(常见做法?)

coder 2024-05-18 原文

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.


3年前关闭。







Improve this question




我开发 jQuery 插件已经有一段时间了,我想我现在知道如何设计一个很好的插件了。一个问题一直困扰着我,那就是如何以一种强大而优雅的方式处理私有(private)函数。

我的插件通常看起来像这样:

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

现在我的问题是:如何巧妙地干掉共享功能?一个明显的解决方案是将它放在插件命名空间内的一个函数中:
var fill = function($obj, color) {
  $obj.css('background-color', color);
};

尽管此解决方案有效且命名空间很好,但我真的不喜欢它。原因很简单:我必须将 jQuery 对象传递给它。 IE。我必须这样调用它:fill(this, 'red'); ,而我想这样调用它:this.fill('red');
当然,我们可以通过简单地输入 fill 来实现这个结果。进入 jQuery.fn .但这感觉非常不舒服。想象一下,有十个基于这种方法开发的插件,每个插件将其中五个“私有(private)”函数放入 jQuery 函数命名空间。它最终陷入了巨大的困惑。我们可以通过在每个函数前面加上它们所属插件的名称来缓解,但这并不能真正使它更具吸引力。这些函数应该是插件私有(private)的,所以我们根本不想将它们暴露给外界(至少不直接暴露)。

所以我的问题是:你们中是否有人对如何两全其美提出建议。那是;插件代码能够以类似于 this.fill('red') 的方式调用“私有(private)”插件函数(或 this.myplugin.fill('red') 甚至 this.myplugin().fill('red') 等),同时防止 jQuery 函数命名空间污染。当然它应该是轻量级的,因为这些私有(private)函数可能会被非常频繁地调用。

更新 : 谢谢你的建议。

我特别喜欢 David 定义一个包含“私有(private)”函数并包装 jQuery 对象的对象类型的想法。唯一的问题是它仍然不允许我链接“私有(private)”和“公共(public)”功能。这是想要 this.fill('red') 这样的语法的重要原因首先。

我最终得到了一个我认为不是非常优雅的解决方案,但对“两全其美”的事业具有吸引力:
$.fn.chain = function(func) {
    return func.apply(this, Array.prototype.slice.call(arguments, 1));
};

它允许以下构造:
this.
    find('.acertainclass').
    chain(fill, 'red').
    click(function() {
        alert("I'm red");
    });

我在其他地方交叉发布了我的问题,其中也收集了一些有趣的回答:
  • http://forum.jquery.com/topic/jquery-plugin-design-pattern-common-practice-for-dealing-with-private-functions
  • http://groups.google.com/group/jquery-en/browse_thread/thread/fa8ccef21ccc589a
  • 最佳答案

    一件事先 : 如果你想调用 this.fill('red');在哪里 这个是 jQuery 的一个实例,你必须扩展 jQuery 原型(prototype)并制作 fill() “上市”。 jQuery 提供了使用所谓的“插件”扩展其原型(prototype)的指南,可以使用 $.fn.fill 添加。 , 与 jQuery.prototype.fill 相同.

    在 jQuery 回调中,这个通常是对 HTML 元素的引用,并且您不能向这些元素添加原型(prototype)(目前)。这就是 jQuery 包装元素并返回可以轻松扩展的 jQuery 实例的原因之一。

    使用 (function(){})();语法,您可以即时创建和执行“私有(private)”javascript,完成后一切都会消失。使用这种技术,您可以创建自己的类似 jQuery 的语法,将 jQuery 包装到您自己的私有(private)可链接对象中。

    (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'
    

    这样,P 代表您自己的“私有(private)”功能工具箱。除非您将它们附加到某个地方,否则它们在代码或 jQuery 命名空间中的其他任何地方都不会可用。您可以在 Private 对象中添加任意数量的方法,只要您返回 这个 ,您也可以像我在示例中所做的那样链接它们 jQuery 样式。

    关于javascript - 用于处理私有(private)函数的 jQuery 插件设计模式(常见做法?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2061501/

    有关javascript - 用于处理私有(private)函数的 jQuery 插件设计模式(常见做法?)的更多相关文章

    1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

      我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

    3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

      大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

    4. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    5. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

      在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

    6. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

      我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

    7. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

      我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

    8. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

      我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

    9. Ruby Sinatra 配置用于生产和开发 - 2

      我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

    10. ruby - 在 Ruby 中有条件地定义函数 - 2

      我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

    随机推荐