如何直接在jQuery插件中调用函数? (样板)

时间:2018-08-10 18:08:09

标签: javascript jquery jquery-plugins

我目前正忙于基于样板设置jQuery插件,但是我似乎无法通过直接调用从外部访问函数,例如:

var myPlugin = $("#container").myPlugin();
myPlugin.someFunction(); // This does not work

$("#container").myPlugin("someFunction") // This works

链接当前如下所示:

$("#container").myPlugin("chainMethod").myPlugin("chainMethod2");

我希望它看起来像这样:

var myPlugin = $("#container").myPlugin();
myPlugin.chainMethod().chainMethod2();

我认为解决第一个问题也会自动解决第二个问题,但是我不知道自己在做什么错。任何解决我的问题的帮助都将受到赞赏。

我的插件代码(带有注释)定义如下:

// the semi-colon before function invocation is a safety net against concatenated
// scripts and/or other plugins which may not be closed properly.
;(function ($, window, document, undefined) {
    "use strict";

    // undefined is used here as the undefined global variable in ECMAScript 3 is mutable (ie. it can be changed
    // by someone else). undefined isn't really being passed in so we can ensure the value of it is truly undefined.
    // In ES5, undefined can no longer be modified.

    // window is passed through as local variable rather than global as this (slightly) quickens the resolution
    // process and can be more efficiently minified (especially when both are regularly referenced in a plugin).

    // Create the defaults once
    var pluginName = 'myPlugin',
        defaults = {
            id: 0,
            propertyName: "value"
        };

    // The actual plugin constructor
    function Plugin(element, options) {
        this.elem = element;
        this.$elem = $(element);

        // jQuery has an extend method which merges the contents of two or more objects, storing the result
        // in the first object. The first object is generally empty as we don't want to alter the default
        // options for future instances of the plugin
        this.settings = $.extend({}, defaults, options);
        this._defaults = defaults;
        this._name = pluginName;
        this.init();
    }

    // Avoid Plugin.prototype conflicts
    $.extend(Plugin.prototype, {
        init: function () {

            // Place initialization logic here. You already have access to the DOM el and
            // the options via the instance, e.g. this.el and this.settings
            this.$elem.text("jQuery Boilerplate");

            this._somePrivateFunc();
        },
        destroy: function () {
            $.data(this, 'plugin_' + pluginName, null);
        },
        someFunction: function () {
            console.log("someFunction");
        },
        _somePrivateFunc: function () {
            console.log("Private Func");
        },    
        someGetterMethod: function () {
            return "This is a getter method";
        },
        chainMethod: function() {
            console.log("Chain");
            return this;
        },
        chainMethod2: function() {
            console.log("Chain 2");
            return this;
        }
    });

    // A really lightweight plugin wrapper around the constructor, preventing against multiple instantiations and
    // allowing any public function (ie. a function whose name doesn't start with an underscore) to be called
    // via the jQuery plugin, e.g. $(el).defaultPluginName('functionName', arg1, arg2)
    $.fn[pluginName] = function (options) {
        var args = arguments;

        // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
        if (options === undefined || typeof options === 'object') {
            return this.each(function () {

                // Only allow the plugin to be instantiated once, so we check that the el has no
                // plugin instantiation yet
                if (!$.data(this, 'plugin_' + pluginName)) {

                    // if it has no instance, create a new one, pass options to our plugin constructor,
                    // and store the plugin instance in the elements jQuery data object.
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });

            // If the first parameter is a string and it doesn't start with an underscore or "contains" the
            // `init`-function, treat this as a call to a public method.
        } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {

            // Call a public plugin method (not starting with an underscore) for each selected element.
            if (Array.prototype.slice.call(args, 1).length == 0 && $.inArray(options, $.fn[pluginName].getters) != -1) {

                // If the user does not pass any arguments and the method allows to work as a getter then
                // break the chainability so we can return a value instead the element reference.
                var instance = $.data(this[0], 'plugin_' + pluginName);
                return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
            } else {

                // Invoke the specified method on each selected element
                return this.each(function () {
                    var instance = $.data(this, 'plugin_' + pluginName);
                    if (instance instanceof Plugin && typeof instance[options] === 'function') {
                        instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                    }
                });
            }
        }
    };

    // Names of the plugin methods that can act as a getter method.
    $.fn[pluginName].getters = ['someGetterMethod'];

}(jQuery, window, document));

谢谢。

0 个答案:

没有答案