Может ли буквальный объект Javascript вызывать события? - PullRequest
4 голосов
/ 03 декабря 2011

У меня есть литерал объекта 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 ]

1 голос
/ 03 декабря 2011

Это должно работать:

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 в функции click.

0 голосов
/ 03 декабря 2011

Если вы хотите иметь возможность вызывать метод для объекта 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

0 голосов
/ 03 декабря 2011

Как насчет этого? :

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.)

...