【问题标题】:Can you use a JS object as the interface for a JQuery plugin?可以使用 JS 对象作为 JQuery 插件的接口吗?
【发布时间】:2014-02-07 11:35:59
【问题描述】:

我看过这个帖子:How to create a jQuery plugin with methods?,虽然有很多关于多功能插件的解决方案,但我很感兴趣是否可以使用一个对象来避免丑陋的结构像$("selector").plugin().dostuff(),而是可以像这样使用它:$("selector").plugin.dostuff(),即'plugin'是一个对象而不是一个函数

我可以这样写插件:

$.fn.plugin = {
    dostuff: function() {},
    domorestuff: function(){}
};

但是内部函数首先无法访问调用它的 JQuery 对象,因为 this 返回插件对象。有没有什么方法可以基于可以与 JQuery 一起使用的对象来构建插件?

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    不,因为您给出的原因:您失去了this,而this 在编写插件时非常重要。要获得this,您的插件必须是一个函数。

    你基本上有三种实现方法的方式:

    1. 使用字符串参数,例如:

      $("selector").plugin("dostuff");
      

      ...您在插件函数中分派到处理程序方法的位置。这是到目前为止最流行的方式。这是 jQuery UI、Bootstrap 等使用的方式。下面的完整示例。

    2. 使用你所说的“丑陋的构造”,你的插件是一个函数,它返回一个对象(每次都是一个新对象,以保留this),其中包含你可以调用的函数。

    3. 1234563冲突。很久以前,我只见过一次这样做,而且我已经有一段时间没有看到那个插件了。不是一个真正受欢迎的选择。

    我最近刚刚发布了this other answer,显示了#1 的完整模式(在他们的例子中,方法是callThisdestroy),例如:

    // Create the plugin
    (function ($) {
        var methods = {
            init: function(options) {
                // Determine options
                var opts = $.extend({
                    opacity: 0.5             
                }, options);
    
                // Remember them
                this.data("pluginname", opts);
    
                // Initial stuff
                this.css("opacity", opts.opacity);
            },
    
            callThis: function(opts) {
                // Use 'opts' if relevant
                this.css("display","none");
            },
    
            destroy: function(opts) {
                this.removeData("pluginame");
                this.css("display", "").css("opacity", "");
            }
        };
    
        jQuery.fn.pluginname = function (options) {
            var method, args;
    
            // Method?
            if (typeof options === "string") {
                // Yes, grab the name
                method = options;
    
                // And arguments (we copy the arguments, then
                // replace the first with our options)
                args = Array.prototype.slice.call(arguments, 0);
    
                // Get our options from setup call
                args[0] = this.data("pluginname");
                if (!args[0]) {
                    // There was no setup call, do setup with defaults
                    methods.init.call(this);
                    args[0] = this.data("pluginname");
                }
            }
            else {
                // Not a method call, use init
                method = "init";
                args = [options];
            }
    
            // Do the call
            methods[method].apply(this, args);
        };
    })(jQuery);
    
    // Example usage
    function doInit() {
      $("#target").pluginname();
      setTimeout(doCallThis, 700);
    }
    function doCallThis() {
      $("#target").pluginname("callThis");
      setTimeout(doDestroy, 700);
    }
    function doDestroy() {
      $("#target").pluginname("destroy");
      setTimeout(doInit, 700);
    }
    
    setTimeout(doInit, 700);
    <div id="target">This is the target</div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    【讨论】:

    • 好吧,你说服了我。但是您能解释一下为什么 this 在您的示例中有效而不在我的示例中有效吗?
    • @Miguel:因为 JavaScript 中的 this 主要由函数的调用方式设置:如果您通过对象属性调用函数,在调用中,this 指的是该对象(通常)。所以foo.bar();调用barthis等于foo$("selector").plugin(); 调用 plugin 时,this 等于 $("selector") 返回的 jQuery 对象。但是$("selector").plugin.method(); 调用methodthis 等于plugin,而不是jQuery 对象;对 jQuery 对象的引用已丢失。
    • 但是在您的情况下methods[method].apply(this, args); 不涉及调用对象“方法”的方法吗?那么为什么this 没有设置为“methods”呢?
    • @Miguel:因为附加到函数的apply(和call)函数很特殊:它们存在的理由是调用具有指定this 值(你给在第一个参数中)。
    猜你喜欢
    • 2015-12-24
    • 2012-07-26
    • 2013-02-07
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2021-07-10
    • 2012-10-02
    • 2011-04-29
    相关资源
    最近更新 更多