最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Destroy Backbone views on route change - Stack Overflow

programmeradmin2浏览0评论

My view should be destroyed after the current route position is left.

So in this schematic example the login view should be destroyed after the user entered his credentials:

I tried to solve this by using Backbone.Router events:

var Router = Backbone.Router.extend({
    initialize: function () {
        Backbone.history.start();
    },
    routes: {
        "sample" : "sample"
    },
    sample: function(){
      // Build view
      var demoView = $("<div/>")
          .appendTo(document.body)  
          .text("I am lost!");

      // Destroy view
      this.once('route', function(){
        demoView.remove(); 
      });
    },
});

Unfortunately this does not work as the route events are raised after the routes are executed:

/

Is there a solution to destroy views after leaving the route position?

Do I have to hack a new event into Backbone.js?

My view should be destroyed after the current route position is left.

So in this schematic example the login view should be destroyed after the user entered his credentials:

I tried to solve this by using Backbone.Router events:

var Router = Backbone.Router.extend({
    initialize: function () {
        Backbone.history.start();
    },
    routes: {
        "sample" : "sample"
    },
    sample: function(){
      // Build view
      var demoView = $("<div/>")
          .appendTo(document.body)  
          .text("I am lost!");

      // Destroy view
      this.once('route', function(){
        demoView.remove(); 
      });
    },
});

Unfortunately this does not work as the route events are raised after the routes are executed:

http://jsfiddle/hcuX9/

Is there a solution to destroy views after leaving the route position?

Do I have to hack a new event into Backbone.js?

Share Improve this question edited Mar 29, 2013 at 20:31 jantimon asked Mar 29, 2013 at 19:06 jantimonjantimon 38.2k23 gold badges126 silver badges193 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

What I use to do is to have an App.current variable pointing to the current view being rendered.

At the top of each route (or the relevant ones in your case), I remove the current view from App.current and then assign it the new view:

someRoute: function() {
  if(App.current && App.current.remove) App.current.remove();  

  // Asign a new current page
  App.current = new SomeView();
  ...
}

That way I only let one view live per route, getting rid of problems like yours.

If you don't like to be checking for App.current and invoking the remove method at the top of every route, you can listen for Backbone.history route event and injecting that logic there:

Backbone.history.on('route', function() {
  if(App.current && App.current.remove) App.current.remove();  
});

I think you are stuck with your hack, unless you can adapt .listenTo to your needs - then you will need to fire a custom event with .trigger anywhere you have a route change, which might not be possible. Note that this functionality has been requested (and denied) before in backbone:

https://github./documentcloud/backbone/pull/494

See that pull request for other patches that try to do the same thing you are doing.

Here, we're using on and off to listen for route events ing in instead of once because we can't rely on a single event not being the current route. When we receive a route even that is not our current route, we can destroy the view and remove the listener:

  // Destroy view
  var self = this;
  var onRoute = function(route, params){
    if(route !== 'sample'){
      demoView.remove();
      self.off('route', onRoute);
    }
  };
  this.on('route', onRoute);

I've modified your test fiddle here: http://jsfiddle/rgthree/hcuX9/3/


Another option, as your fiddle (not in your question) navigates directly to another view. This causes the other route's event to fire after the sample2 route. Because of this the above will remove the view. Now, it's much more plete. A hackier way you could handle it is to simply defer the once in a setTimeout so it doesn't listen until after the current route has been fired:

// Destroy view
var self = this;
setTimeout(function(){        
  self.once('route', function(){
    demoView.remove(); 
  });
}, 0);

You can see your fiddle with this method here: http://jsfiddle/rgthree/hcuX9/4/

发布评论

评论列表(0)

  1. 暂无评论