【问题标题】:How to expose public properties with jQuery plugins?如何使用 jQuery 插件公开公共属性?
【发布时间】:2014-10-10 04:04:00
【问题描述】:

我正在使用 jQuery 构建一个小插件,但我希望它能够将它的一些数据公开为公共属性。例如:

$(function () {
        $("#example1").myPlugin({
            exampleData: 'bar'
        });
        $("#example2").myPlugin({
            exampleData: 'foo'
        });
        $("#example3").myPlugin({
            exampleData: 'too'
        });

        $('.click').click(function () {
            console.log($("#example1").myPlugin('getData'));
            console.log($("#example2").myPlugin('getData'));
            console.log($("#example3").myPlugin('getData'));
        });
    });

我希望控制台上的结果是:

'bar'
'foo'
'too'

我尝试使用以下代码来完成此操作:

(function ($) {
$.myPlugin = function (options) {
    $.myPlugin.settings = $.extend({
        exampleData: 'default value'
    }, options);
}

$.fn.myPlugin = function (methodOrOptions) {
    var methods = {
        getData: function () {
            return $(this).settings.exampleData;
        },
        init: function (options) {
            new $.myPlugin(options);
        }
    }

    if (methods[methodOrOptions]) {
        return methods[methodOrOptions].apply($(this), Array.prototype.slice.call(arguments, 1));
    } else if (typeof methodOrOptions === 'object' || !methodOrOptions) {
        return methods.init.apply($(this), arguments);
    } else {
        $.error('Method ' + methodOrOptions + ' does not exist on jQuery.myPlugin');
    }
};
})(jQuery);

但我得到“无法获取未定义或空引用的属性 'exampleData'”

谁能帮我解决这个问题?

【问题讨论】:

    标签: jquery plugins methods properties public


    【解决方案1】:

    主要问题在于这一行:

    return $(this).settings.exampleData;
    

    $(this) 返回一个 jQuery 集合,而 jQuery 集合没有 settings 属性。

    在编写插件时要记住的一件主要事情是,您会使用 jQuery 集进行调用,但您所做的一切都只能在该集的子集上工作。示例:

    // Initialize on a set that includes *all* paragraphs
    $("p").myPlugin();
    
    // ...
    
    // But now we do something with just the third paragraph; the
    // plugin should expect that and store information on a per-
    // element basis, not a per-set basis
    $("p").eq(2).myPlugin("doSomething");
    

    一种相当简单的方法是使用 jQuery 的 data 函数存储信息。

    对于它的价值,这里有一个基本插件的例子,它有“setData”和“getData”方法。代码中cmets中的详细信息:

    (function($) {
        "use strict";
    
        // Defaults
        var defaults = {
            // ...
        };
    
        // Methods
        var methods = {
            // (Note that `initialize` isn't on this list)
            getData:    getData,
            setData:    setData
        };
    
        // Utils
        var slice = Array.prototype.slice;
    
        // Expose the plugin
        $.fn.myPlugin = myPlugin;
    
        // Main entry point to plugin
        function myPlugin(arg) {
            var args = slice.call(arguments, 0);
            var method;
            var rv;
    
            // What are we doing?
            switch (typeof arg) {
                case "undefined":
                case "object":
                    // Initializing
                    rv = initialize.call(this, args);
                    break;
    
                case "string":
                    // Method, do we know it?
                    method = methods[arg];
                    if (!method) {
                        throw new Error("myPlugin: Unknown method '" + arg + "'");
                    }
                    args.shift(); // We've consumed the method name
    
                    // Do it, return whatever it returns
                    rv = method.call(this, args);
                    break;
    
                default:
                    throw new Error("myPlugin: Expected string or object as first argument if argument given.");
            }
    
            return rv;
        }
    
        // Initialize the plugin
        function initialize(args) {
            // Get the options
            var options = $.extend({}, defaults, args[0]);
    
            // Loop through, initializing the elements
            this.each(function() {
                // ...
                // (if appropriate here, you might detect whether you're being re-initialized
                // for the same element)
            });
    
            // Enable chaining
            return this;
        }
    
        // Get data
        function getData(args) {
            // "Get" operations only apply to the first element
            // Return the data; normally `args` wouldn't be used
            return this.first().data("myPlugin");
        }
    
        // Set data; "set" operations apply to all elements
        function setData(args) {
            this.data("myPlugin", args[0]);
            return this;
        }
    })(jQuery);
    

    Live Example

    【讨论】:

    • 这就是我所说的详尽答案 - 非常感谢,它对我帮助很大。顺便说一句,我没有在问题中提到它,但是有没有办法将插件的使用限制为仅限于独特的元素?意思是,只有当 jQuery 选择器类似于 $('#uniqueElement') 而不是 $('p') 或 $('.someElementClass #anotherElementUniqueId .theElement') 时才允许插件工作的限制?如果出现这种情况,我该如何检查并抛出错误?
    • @T.J. Crowder:背景:我不是前端人员... 两个快速的问题:arguments 来自var args = slice.call(arguments, 0); 行中的哪里以及如何访问这些选项?我不明白你是如何从var options = ... 获得插件中可用的,如果那个 var 不在其他任何地方,并且没有返回? -- 第三个问题(对不起)你能给我指出一个方向来理解initialize函数中的($this).each()吗?我知道($this).each() 做了什么——我只是不明白在这种情况下它会做什么
    • @PhillipHarrington:所有非箭头函数都有一个自动 arguments 对象,其中包含调用它们的参数:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
    • @PhillipHarrington:(重新编辑)您将在 each 回调中的代码中使用 options。回复each:使用this 调用插件,指的是调用它们的jQuery 对象。所以this.each是使用api.jquery.com/each对jQuery对象中的每个元素进行操作。
    • @T.J.Crowder - 我为什么不直接说 this.options = $.extend({}, defaults, args[0])each() 函数是否必须进行切换才能查看 arg 是什么?
    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 2011-10-07
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多