MooTools связывает / сохраняет область видимости класса в методах и внутренних функциях - PullRequest
1 голос
/ 15 декабря 2011

Я пытаюсь использовать Mootools для динамического добавления кнопки на страницу.Все работает нормально, кроме addEvent в функции addButton.Я получаю сообщение об ошибке, говорящее, что «свойство 'sayHi' объекта javascript: void (0); не является функцией".

Я предполагаю, что это связано с моей областью действия и что я каким-то образом должен связать функцию addButtonк глобальному «это»?Может кто-нибудь объяснить, что я делаю не так?Спасибо!

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    this.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    

Ответы [ 4 ]

2 голосов
/ 15 декабря 2011

Вы получаете эту проблему, потому что когда выполняется обработчик click, this представляет объект элемента anchor, а не ваш myClass.

.1008 *

addButton: function(){
    var that = this;
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: 'javascript:void(0);',
        events: {
            click: function(){
                that.sayHi();
            }
        }
    }).inject($('myDiv'));
}

ЗДЕСЬ - пример работы.Переключитесь в режим просмотра кода для просмотра исходного кода.

2 голосов
/ 15 декабря 2011

Проблема в том, что в вашем обработчике кликов значение this больше не является исходным объектом, а скорее кнопкой, на которую нажали кнопку., но оборачивание создания этого объекта в функцию было бы простым, родным способом решить эту проблему:

function getMyClass(){
   var self = new Class({
       initialize: function(){
           this.sayHi();
       },

       sayHi: function(){
           alert('Hello World!');
       },

       addButton: function(){
           this.hiButton = new Element('a', {
               id: 'sayhi',
               html: 'Hi!',
               href: 'javascript:void(0);',
               events: {
                   click: function(){
                       self.sayHi();
                   }
               }
          }).inject($('myDiv'));
       }
   });

   return self;
}    

А затем

var myClass = getMyClass();

EDIT

Хотя вышеприведенное является довольно стандартной идиомой в JavaScript, мне сказали, что оно не очень хорошо работает с MooTools.Если это так, я бы пошел с этим (как уже упоминалось в другом ответе):

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});    
1 голос
/ 11 января 2012

OMG, а как насчет связывания?Делать var self = this; просто неправильно.Вы можете сделать что-то вроде этого:

var myClass = new Class({
initialize: function(){
    this.sayHi();
},

sayHi: function(){
    alert('Hello World!');
},

addButton: function(){
    this.hiButton = new Element('a', {
        id: 'sayhi',
        html: 'Hi!',
        href: '#',
        events: {
            click: function(){
                this.sayHi();

                // this will stop event propagation
                return false;
            }.bind(this)
        }
    }).inject($('myDiv'));
}
});  

Вы можете проверить это здесь

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

Рекомендованный способ справиться с этим и во многих плагинов mootools следующий:

var myClass = new Class({
    initialize: function(){
        this.sayHi();
    },

    sayHi: function(){
        alert('Hello World!');
    },

    addButton: function(){
        var self = this;
        this.hiButton = new Element('a', {
            id: 'sayhi',
            html: 'Hi!',
            href: 'javascript:void(0);',
            events: {
                click: function(){
                    self.sayHi();
                }
            }
        }).inject($('myDiv'));
    }
});

Вы можете видеть, что это очень похоже на решение Адама Ракиса, но вам не нужно заключать в класс вызов функции.

ИМХО это делает код немного чище / удобнее / размышлять!

Надеюсь, это поможет.

...