【问题标题】:Destroy Backbone views on route change销毁路由更改的主干视图
【发布时间】:2013-03-29 19:06:07
【问题描述】:

离开当前路线位置后,我的视图应该被销毁。

所以在这个示意图示例中,登录视图应该在用户输入他的凭据后被销毁:

我试图通过使用Backbone.Router 事件来解决这个问题:

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(); 
      });
    },
});

不幸的是,这不起作用,因为路由事件在 路由执行后引发:

http://jsfiddle.net/hcuX9/

有没有办法在离开路由位置后销毁视图?

我必须 hack a new event 进入 Backbone.js 吗?

【问题讨论】:

    标签: javascript jquery backbone.js backbone-views backbone-routing


    【解决方案1】:

    我用来做的是有一个App.current 变量指向当前正在渲染的视图。

    在每条路线的顶部(或您的情况下的相关路线),我从App.current 中删除当前视图,然后为其分配新视图:

    someRoute: function() {
      if(App.current && App.current.remove) App.current.remove();  
    
      // Asign a new current page
      App.current = new SomeView();
      ...
    }
    

    这样我每条路线只让一个视图直播,摆脱像你这样的问题。

    如果您不喜欢检查 App.current 并在每条路由的顶部调用 remove 方法,您可以侦听 Backbone.history 路由事件并在那里注入该逻辑:

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

    【讨论】:

    • 不幸的是route事件是在路由执行后触发的。
    【解决方案2】:

    我认为你被你的黑客所困扰,除非你可以调整 .listenTo 以适应你的需求 - 那么你将需要在你有路由更改的任何地方使用 .trigger 触发一个自定义事件,这可能是不可能的。请注意,此功能之前已在骨干网中被请求(并被拒绝):

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

    查看其他试图做你正在做的事情的补丁的拉取请求。

    【讨论】:

      【解决方案3】:

      在这里,我们使用onoff 来监听路由事件,而不是once,因为我们不能依赖单个事件不是当前路由.当我们收到一个不是我们当前路由的路由时,我们可以销毁视图并移除监听器:

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

      我在这里修改了你的测试小提琴:http://jsfiddle.net/rgthree/hcuX9/3/


      另一个选项, 当您的小提琴(不在您的问题中)直接导航到另一个视图时。这会导致其他路由的事件在 sample2 路由之后触发。因此,上述内容将删除该视图。现在,它更加完整。您可以处理它的一种更巧妙的方法是简单地将once 推迟到setTimeout 中,这样它直到当前路由被触发后才会监听:

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

      您可以在此处查看您使用此方法的方法:http://jsfiddle.net/rgthree/hcuX9/4/

      【讨论】:

      • 我看不出这与我的代码有什么不同。你能提供一个小提琴吗?
      • 反对票是怎么回事?这是正确的答案。我的代码与您的不同,因为您使用的是once,它只触发一次。不幸的是,那一次火灾在错误的时间移除了视图监听器。您要做的只是在另一条当前路由(此处为“示例”)时移除视图和侦听器。因此,您需要使用onoff 来控制监听器。我将添加您的测试小提琴的修改版本:jsfiddle.net/rgthree/hcuX9/3
      • 你是对的。你知道为什么,对吧?这是因为第一个路由的路由事件是在第二个路由事件之后触发的,所以是不同的。你可以很容易地解决这个问题.. 但你的问题没有要求重定向,所以,我确实 100% 正确地回答了你的问题......
      • 路线改变后,我正在寻找一种适当的方式来破坏我的视野。您的解决方案并非在所有情况下都有效。
      • 我明白了。一个 hacky 方法是将 once 方法推迟到 setTimeout 中,这样它直到当前路由触发后才开始侦听。你可以在这里看到它:jsfiddle.net/rgthree/hcuX9/4
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-14
      • 2016-07-21
      • 2021-01-07
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      相关资源
      最近更新 更多