Может ли JavaScript Literal Object Fire Events?
-
27-10-2019 - |
Вопрос
У меня есть буквальный объект 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
Событие на объекте инструментов Literal, а не на панели инструментов DOM, упомянутый в буквальном языке. Возможно ли это, и если да, то как бы я это сделал?
Решение
Это должно работать:
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
Вам нужно поддерживать
this
Ссылка в функции щелчка. я использовал$.proxy
; Некоторые люди используютvar self = this;
Toolbar
не является объектом jQuery, поэтому он должен быть завернут в$()
Чтобы получить доступ к функциям jQuery. Также обернитеthis
это относится кToolbar
экземпляр в функции щелчка.
Другие советы
Как насчет этого? :
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.)
Если вы хотите иметь возможность вызвать метод на 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.