Backbone.Marionette: Отложить просмотр до закрытия до завершения анимации закрытия

Я пытаюсь настроить анимацию на рендеринг и закрытие ItemView с помощью Backbone.Marionette. Для рендеринга представления это довольно просто:

MyItemView = Backbone.Marionette.View.extend({
   ...
   onRender: function() {
     this.$el.hide().fadeIn();
   }
   ...
});

Это приведет к тому, что мой взгляд исчезнет, ​​когда я его обработаю. Но позвольте сказать, что я хочу постепенно прекратить свое мнение.

beforeClose: function() {
   this.$el.fadeOut();       // doesn't do anything....
}

Это не сработает, потому что элемент закрывается сразу после вызова this.beforeClose(), поэтому анимация не успевает закончить.

Есть ли способ, используя марионетку в ее нынешнем виде, выполнить заключительную анимацию?


В качестве альтернативы это обходной путь, который я использовал:

_.extend(Backbone.Marionette.ItemView.prototype, {
    close: function(callback) {

        if (this.beforeClose) {

            // if beforeClose returns false, wait for beforeClose to resolve before closing
            // Before close calls `run` parameter to continue with closing element
            var dfd = $.Deferred(), run = dfd.resolve, self = this;
            if(this.beforeClose(run) === false) {
                dfd.done(function() {
                    self._closeView();              // call _closeView, making sure our context is still `this`
                });
                return true;
            }
        }

        // Run close immediately if beforeClose does not return false
        this._closeView();
    },

// The standard ItemView.close method.
    _closeView: function() {
        this.remove();

        if (this.onClose) { this.onClose(); }
        this.trigger('close');
        this.unbindAll();
        this.unbind();      
    }
});

Теперь я могу это сделать:

beforeClose: function(run) {
    this.$el.fadeOut(run);      // continue closing view after fadeOut is complete
    return false;
},

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

Это потенциально может быть использовано для других целей, таких как запрос подтверждения при закрытии (см. issue) или запуска любого типа асинхронного запроса.

Мысли?

Ответ 1

Переопределение метода close - это один из способов сделать это, но вы можете записать его бит короче, так как вы можете вызвать метод Marionettes close, а не дублировать его:

_.extend(Backbone.Marionette.ItemView.prototype, {
    close: function(callback) {
        var close = Backbone.Marionette.Region.prototype.close;
        if (this.beforeClose) {

            // if beforeClose returns false, wait for beforeClose to resolve before closing
            // Before close calls `run` parameter to continue with closing element
            var dfd = $.Deferred(), run = dfd.resolve, self = this;
            if(this.beforeClose(run) === false) {
                dfd.done(function() {
                    close.call(self);
                });
                return true;
            }
        }

        // Run close immediately if beforeClose does not return false
        close.call(this);
    },


});

Другая идея - переопределить метод remove вашего представления. Таким образом, вы уменьшаете элемент представления, а затем удаляете его из DOM

remove: function(){
  this.$el.fadeOut(function(){
    $(this).remove();
  }); 
}