简体   繁体   English

在Click事件中访问Javascript类对象

[英]Accessing Javascript Class Object In Click Event

I have been trying to learn how to build jQuery plugins, so I'm still new at this. 我一直在尝试学习如何构建jQuery插件,因此我仍然是新手。 Since this is my first plugin, I decided I would try a simple collapsible panel/box (you can only read so much, right?). 因为这是我的第一个插件,所以我决定尝试一个简单的可折叠面板/盒(您只能读很多东西,对吧?)。 I'm having difficulty accessing my reference to my Javascript class object when the click event triggers. 当点击事件触发时,我很难访问对Javascript类对象的引用。 I know that this inside of the event refers to the element that triggered the event. 我知道事件内部的内容是指触发事件的元素。 I also know that I can do something like _self = this; 我也知道我可以做类似_self = this;事情_self = this; before the event, but that will only cache the last object from the collection. 事件之前,但这只会缓存集合中的最后一个对象。 Does anyone have any suggestions on how I can keep a reference to the class object? 有人对我如何保留对类对象的引用有任何建议吗?

Thanks! 谢谢!

Here is my code. 这是我的代码。

HTML code HTML代码

<div class="mypanel" title="Panel 1">Testing panel 1</div>
<div class="mypanel" title="Panel 2">Testing panel 2</div>
$('.mypanel').collapsiblePanel();

Plugin code 插件代码

var contentVisible = 'showContent', contentNotVisible = 'hideContent';

;(function($) {
    var pluginName = 'collapsibleBox';

    function Plugin(element, options) {
        this.ele = element;
        this.$ele = $(element);
        var _self = this;

        this.options = $.extend({}, $.fn[pluginName].defaults, options);

        this.init();

        /* Expose methods of Plugin we wish to be public.
         * This gets stored when the plugin is created
         */
        return {
            option: this.option,
            destroy: this.destroy
            /* Other public methods here */
        }
    }
    $.fn[pluginName] = function(options) {
        /* If the first parameter is a string, treat this as a call to a public method. */
        if(typeof arguments[0] === 'string') {
            var methodName = arguments[0];
            var args = Array.prototype.slice.call(arguments, 1);
            var returnVal;
            this.each(function() {
                /* Check that the element has a plugin instance, and that
                 * the requrested public method exists.
                 */
                if($.data(this, 'plugin_' + pluginName) && typeof $.data(this, 'plugin_' + pluginName)[methodName] === 'function') {
                    /* Call the method of the Plugin instance, and Pass it the supplied arguments */
                    returnVal = $.data(this, 'plugin_' + pluginName)[methodName].appy(this, args);
                }
                else {
                    $.error('Method ' + methodName + ' does not exist on jQuery.' + pluginName);
                }
            });
            if(returnVal !== undefined) {
                /* If the method returned something, return it */
                return returnVal;
            }
            else {
                /* Otherwise, returning 'this' preserves chainability */
                return this;
            }
        }
        /* If the first parameter is an object (options), or was omitted,
         * instantiate a new instance of the plugin
         */
        else if(typeof options === 'object' || !options) {
            return this.each(function() {
                /* Only allow the plugin to be instantiated once */
                if(!$.data(this, 'plugin_' + pluginName)) {
                    /* Pass options to Plugin constructor, and store Plugin
                     * instance in the element's jQuery data object
                     */
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        }
    };

    $.fn[pluginName].defaults = {
        onInit: function() {},
        onDestroy: function() {}
    };

    Plugin.prototype = {
        init: function() {
            this.createContentArea();
            this.createTitleBar();
            this.hook('onInit');
        },
        createContentArea: function() {
            /* ... */
        },
        createTitleBar: function() {
            /* ... */

            this.$title.click(function() {
                if(this.$ele.data('state') == contentVisible) { // The problem is here
                    this.collapse();
                }
                else {
                    this.expand();
                }
            });
        },
        expand: function() {
            this.$content.slideDown();
            this.$ele.data('state', contentVisible);
        },
        collapse: function() {
            console.log(this);
            this.$content.slideUp();
            this.$ele.data('state', contentNotVisible);
        },
        /* Use this function to get/set variables */
        option: function (key, val) {
            if(val) {
                this.options[key] = val;
            }
            else {
                return this.options[key];
            }
        },
        destroy: function () {
            /* ... */
        },

        hook: function (hookName) {
            if(this.options[hookName] !== undefined) {
                this.options[hookName].call(this.ele);
            }
        }
    };
})(jQuery);

I have managed to fix this issue using a combination of the .data() method and the .call() method to ensure that the context of the function call is always the parent element. 我设法通过结合使用.data()方法和.call()方法来解决此问题,以确保函数调用的上下文始终是父元素。 I managed to get this working using the pattern I had as well as using the pattern suggested by the jQuery Plugin Authoring Tutorial. 我设法使用我以前使用的模式以及jQuery Plugin Authoring Tutorial建议的模式来使此工作正常。 Whether this was the correct way to do it or not, I don't know. 我不知道这是否是正确的方法。

var methods = {
    init: function(options) {
        var $this = $(this), data = {};
        /* Set a local copy of the options */
        data.options = $.extend({}, defaults, options);
        /* Create the content area */
        data.$content = createContentArea(this);
        /* Create the title bar */
        data.$title = createTitleBar(this, data.options.header, data.options.title);

        /* Show/Hide the content based on the default state passed in */
        if(data.options.defaultState == contentVisible) {
            data.$content.show();
            data.state = contentVisible;
        }
        else {
            data.$content.hide();
            data.state = contentNotVisible;
        }

        /* Add the title click event */
        data.$title.click(function() {
            methods.toggle.call($(this).parent());
        });

        /* Add the public methods */
        data.methods = {
            toggle: methods.toggle, 
            expand: methods.expand, 
            collapse: methods.collapse
        };
        return data;
    }, 
    toggle: function() {
        var $this = $(this), data = $this.data('plugin_' + pluginName);
        if(data.state == contentVisible) {
            methods.collapse.call(this);
        }
        else if(data.state == contentNotVisible) {
            methods.expand.call(this);
        }
    }, 
    expand: function() {
        var $this = $(this), data = $this.data('plugin_' + pluginName);
        data.$content.slideDown();
        data.state = contentVisible;
        $this.data('plugin_' + pluginName, data);
    }, 
    collapse: function() {
        var $this = $(this), data = $this.data('plugin_' + pluginName);
        data.$content.slideUp();
        data.state = contentNotVisible;
        $this.data('plugin_' + pluginName, data);
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM