Javascript文字对象可以触发事件吗?

时间:2011-12-03 02:36:56

标签: javascript jquery events object-literal

我有一个Javascript对象文字:

var Toolbar = {

    init: function(toolbar) {
        this.Bar = $(toolbar); // scope is Toolbar object literal

        this.Bar.find('clearButton').click(function() {
            this.trigger('clear'); // doesn't work!
            this.Bar.trigger('clear'); // works!
    }
}

Toolbar.init($('div.toolbar'));
Toolbar.bind('clear', function() { ... }); // doesn't work!
Toolbar.Bar.bind('clear', function() { ... }); // works!

我希望能够在工具栏对象文字上触发clear事件,而不是在文字中引用的工具栏DOM对象。这是可能的,如果是的话,我该怎么做?

3 个答案:

答案 0 :(得分:1)

这应该有效:

var Toolbar = {

    init: function(toolbar) {
        this.Bar = $(toolbar); // scope is Toolbar object literal

        this.Bar.find('.clearButton').click($.proxy(function() {
            $(this).trigger('clear'); // should work now
            this.Bar.trigger('clear'); // still works
        }, this));
    }
};

Toolbar.init($('div.toolbar'));

$(Toolbar).bind('clear', function() { 
    console.log('Toolbar'); 
}); // should work now

Toolbar.Bar.bind('clear', function() { 
    console.log('Toolbar.Bar'); 
}); // still works
  1. 您需要在点击功能中维护this引用。我用$.proxy;有些人使用var self = this;

  2. Toolbar不是jQuery对象,因此它应该包含在$()中以访问jQuery的函数。同时在点击函数中包含引用this实例的Toolbar

答案 1 :(得分:0)

这个怎么样? :

var Toolbar = {

    init: function(toolbar) {
        this.Bar = $(toolbar); // scope is Toolbar object literal

        this.trigger =
            function() { this.Bar.trigger.apply(this.Bar, arguments); };

        this.bind = function() { this.Bar.bind.apply(this.Bar, arguments); };

        this.Bar.find('clearButton').click(function() {
            this.trigger('clear');
    }
};

Toolbar.init();
Toolbar.bind('clear', function() { ... });

如果需要,您可以轻松创建一个处理包装的功能;这些中的任何一个,如你所愿:

function wrapperitize(wrapper, wrappee, method /*, more_methods...*/)
{
    wrapper[method] = function() { wrappee[method].apply(wrappee, arguments); };
    for(var i = 3; i < arguments.length; ++i)
        wrapperitize(wrapper, wrappee, arguments[i]);
}

function wrapperitize(wrapper, wrappeeProp, method /*, more_methods...*/)
{
    wrapper[method] = function()
    {
        wrapper[wrappeeProp][method].apply(wrapper[wrappeeProp], arguments);
    };
    for(var i = 3; i < arguments.length; ++i)
        wrapperitize(wrapper, wrappeeProp, arguments[i]);
}

前者称为wrapperitize(this, this.Bar, 'trigger', 'bind'),后者称为wrapperitize(this, 'Bar', 'trigger', 'bind')(不同之处在于前者会使this成为当前this.Bar的包装器而后者会使this成为未来this.Bar可能成为的包装器。

(顺便说一句,顺便说一下,递归的一点点。这是为了避免有问题的变量捕获,因为JavaScript中的闭包工作方式。)

答案 2 :(得分:0)

如果您希望能够在Toolbar对象上调用方法,则需要在那里定义它。如果您不需要以这种方式添加很多这些方法,您可以在工具栏对象本身中定义它们中的每一个:

var Toolbar = {
    clear: function() { this.Bar.trigger('clear'); }

    init: function(toolbar) {
        this.Bar = $(toolbar); // scope is Toolbar object literal
        this.Bar.find('clearButton').click(function() {
            this.clear(); 
    }
}

然而,如果你需要打电话给很多人,这很快就会变得难看。如果确实希望能够调用工具栏对象上jquery对象的所有可用方法,则可以尝试使用for in循环遍历所有这些方法并添加它们到工具栏对象,但这将是乏味的,令人讨厌,低效,并可能导致一些错误。每当你想要在该对象上调用一个方法时,我只会使用$(toolbar),因为它摆脱了所有这些缺点。 :d