JavaScript несколько экземпляров объекта, не может правильно получить доступ к свойствам внутри обработчика событий - PullRequest
1 голос
/ 29 мая 2011

У меня есть рабочая версия HTML5 drag & drop для загрузки файлов.Я редактировал код JS для поддержки нескольких загрузок файлов на одной странице.Я столкнулся с проблемой, пытаясь получить доступ к свойствам «экземпляра» в методах, которые зарегистрированы как события.

Проблема показана в приведенном ниже коде в методе this.drop .Причиной существования свойства this. $$ upload_self является доступ к данным через это свойство.Например, я не могу использовать ключевое слово this внутри функции this.drop , потому что при возникновении события this не ссылается на мой "экземпляр".

Я не уверен, что создание $$ upload_self было хорошей идеей.

Новая область экземпляров, созданная так:

  var recording_upload = new upload();
  recording_upload.init(recording_upload, ...);

КодDrag & drop загрузка файла:

    var upload = function() {
    this.$$upload_self = null;
    this.$drop = null;
    this.$status = null;
    this.$progress = null;
    this.maxNumberOfFiles = null;
    ...

    this.init = function (self, pUrl, maxNmbOfFiles, dropArea, progress, status) {
        $$upload_self = self;
        $$upload_self.postUrl = pUrl;
        $$upload_self.maxNumberOfFiles = maxNmbOfFiles;

        $$upload_self.$drop = $("#" + dropArea);
        $$upload_self.$progress = $("#" + progress);
        $$upload_self.$status = $("#" + status);

        $$upload_self.$drop.bind('dragenter', $$upload_self.enter);
        $$upload_self.$drop.bind('dragleave', $$upload_self.leave);
        $$upload_self.$drop.bind('drop', $$upload_self.drop);
    };

    this.enter = function (e) {
        $(e.target).addClass('hover');
        return false;
    };

    this.leave = function (e) {
        $(e.target).removeClass('hover');
        return false;
    };

    this.drop = function (e, _this) {
        $(e.target).removeClass('hover');
        var files = e.originalEvent.dataTransfer.files;

        if (files.length > $$upload_self.maxNumberOfFiles) { // for example, here $$upload_self references always last instance...
            $$upload_self.displayErrorMessage('Error: You can only drop ' + $$upload_self.maxNumberOfFiles + ' file(s) at time.');
            return false;
        }
     ...
    };
    ...
}

Есть ли обходной путь для решения этой проблемы?Я считаю, что это, возможно, общая проблема, но не могу найти ничего, чтобы решить эту проблему.

Любая помощь очень ценится.

Ответы [ 3 ]

1 голос
/ 29 мая 2011

В современном браузере вы можете сделать это:

  $$upload_self.$drop.bind('dragleave', $$upload_self.leave.bind($$upload_self));

Для более старых версий IE вы можете сделать это:

  $$upload_self.$drop.bind('dragleave', function() { $$upload_self.leave(); });

Действительно метод ".bind ()" для всехОбъекты функций в новых браузерах просто создают для вас небольшую промежуточную функцию, по сути, как во втором примере.Страница Mozilla docs для ".bind ()" содержит очень хороший блок кода, который можно использовать как патч "polyfill" для браузеров, которые изначально не поддерживают ".bind ()".

1 голос
/ 29 мая 2011

Вы можете полностью исключить ключевое слово new и использовать новое закрытие для каждого экземпляра upload.

РЕДАКТИРОВАТЬ: Обновлено, чтобы избежать потенциального слипания глобального this.

var upload = function(pUrl, maxNmbOfFiles, dropArea, progress, status) {
    return {
        postUrl: pUrl,
        ...
        drop: function(e) {
            ...
            if (files.length > this.maxNumberOfFiles) {
                this.displayErrorMessage(...);
            }
            ...
        },
        ...
    };
};

...

var someUpload = upload(...);
1 голос
/ 29 мая 2011

Попробуйте найти "область". В качестве примера посмотрим, как это реализовано в ExtJS.

...