简体   繁体   中英

Backbone.Marionette extending region stops onClose() function from calling

I've created a Backbone, Marionette and Require.js application and am now trying to add smooth transitioning between regions.

To do this easily* ive decided to extend the marionette code so it works across all my pages (theres a lot of pages so doing it manually would be too much)

Im extending the marionette.region open and close function. Problem is that it now doesnt call the onClose function inside each of my views.

If I add the code directly to the marionette file it works fine. So I'm probably merging the functions incorrectly, right?

Here is my code:

extendMarrionette: function () {
  _.extend(Marionette.Region.prototype, {

    open : function (view) {
      var that = this;

      // if this is the main content and should transition
      if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
        this.$el.empty().append(view.el);
        $(document).trigger("WrapperContentChanged")

      } else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {
        $(document).on("WrapperIsHidden:open", function () {

          //swap content
          that.$el.empty().append(view.el);

          //tell router to transition in
          $(document).trigger("WrapperContentChanged");

          //remove this event listener
          $(document).off("WrapperIsHidden:open", that);
        });

      } else {
        this.$el.empty().append(view.el);
      }

    },

    //A new function Ive added - was originally inside the close function below. Now the close function calls this function.
    kill : function (that) {
      var view = this.currentView;
      $(document).off("WrapperIsHidden:close", that)
      if (!view || view.isClosed) {
        return;
      }

      // call 'close' or 'remove', depending on which is found
      if (view.close) {
        view.close();
      }
      else if (view.remove) {
        view.remove();
      }

      Marionette.triggerMethod.call(that, "close", view);

      delete this.currentView;
    },

    // Close the current view, if there is one. If there is no
    // current view, it does nothing and returns immediately.
    close : function () {
      var view = this.currentView;
      var that = this;

      if (!view || view.isClosed) {
        return;
      }

      if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === true) {
        this.kill(this);

      } else if (this.$el.attr("id") === "wrapper" && document.wrapperIsHidden === false) {

        //Browser bug fix - needs set time out
        setTimeout(function () {
          $(document).on("WrapperIsHidden:close", that.kill(that));
        }, 10)


      } else {
        this.kill(this);
      }

    }

  });
}

Why don't you extend the Marionette.Region? That way you can choose between using your custom Region class, or the original one if you don't need the smooth transition in all cases. (And you can always extend it again if you need some specific behavior for some specific case).

https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.region.md#region-class

var MyRegion = Marionette.Region.extend({
    open: function() {
        //Your open function
    }

    kill: function() {
        //Your kill function
    }

    close: function() {
        //Your close function
    }
});

App.addRegions({
    navigationRegion: MyRegion
});

Perhaps your issue is that you are not passing a function to your event listener, but instead calling the code directly in the code below.

setTimeout(function(){
  $(document).on("WrapperIsHidden:close", that.kill(that));
}, 10)

It is likely that you want something like this:

setTimeout(function(){
  $(document).on("WrapperIsHidden:close", function (){ that.kill(that); });
}, 10)

Another possible problem is that you are mixing up your references to this / that in your kill function. It seems like you probably want var view to either be assigned to that.view or to use this rather than that throughout the method.

Answer to your additional problems:

You should try passing the view variable from the close function directly into your kill function because the reference to currentView is already changed to the new view object when you actually want to old view object. The reason this is happening is that you are setting a timeout before executing the kill function. You can see this if you look at the show source code. It expects close , open and then currentView assignment to happen synchronously in order.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM