【问题标题】:Backbone.js: Model, Collection, Router, when and why?Backbone.js:模型、集合、路由器,何时以及为什么?
【发布时间】:2012-05-13 17:45:13
【问题描述】:

我仍在努力了解 Backbone.js 我观看了一些截屏视频并阅读了一些教程。我也是RTFM。但是,对于每个人似乎如何使用框架的某些部分来处理不同的任务,我有点困惑。

在玩过传统的待办事项列表应用程序之后,我决定在一个真正的应用程序中首次尝试使用backbone.js。

我的应用将收到一个包含问题的 JSON 对象。然后,我喜欢有一个“ul”,我可以在其中绕过这些问题(下一个 q,上一个 q)。我已经有一个显示按钮的视图,并在用户单击“下一个”或“上一个”时通知。我的问题是:我应该在哪里处理“currentQuestion”、“next”和“previous”功能的逻辑。我见过一些人为此使用 Collection,而另一些人则使用 Model。这让我很困惑。

谁能给我一些元代码来处理这个问题?非常感谢!

【问题讨论】:

    标签: javascript model-view-controller backbone.js underscore.js


    【解决方案1】:

    这个问题没有真正的正确答案。肯定有不止一种方法可以让它工作,这是 Backbonejs 的优点之一:它非常灵活,不会强加给你太多的设计选择。

    如果我要开始构建您所描述的内容,我肯定会:

    • Question 模型
    • Questions 集合
    • QuestionView 用于呈现单个问题
    • QuestionsIndexView 用于显示问题列表

    在那之后事情变得有点模糊,这取决于您对应用程序的要求。如果您希望像传统网站一样存储状态,则可以使用路由器并执行如下所示的操作:

     ApplicationRouter = Backbone.Router.extend({
    
        routes: {
           "": "index",
           "question/:id": "show"
        },
    
        index: function() {
            // render a QuestionsIndexView...
        },
    
        show: function(id) {
            // find the q and render a QuestionView...
        }
     })
    

    这很好,因为在 URL 中维护了状态,因此用户可以使用浏览器的前进和后退按钮,并且事情可能会按照他们的预期工作。问题是,我们应该如何让nextQuestionpreviousQuestion 按钮工作?

    如果您将它们作为QuestionView 的一部分,则问题必须知道其下一个和上一个问题的 ID 是什么。您可能会想出一个方案来完成这项工作,但更优雅和更常用的模式是创建另一个模型,该模型存在于我们已经提到的所有数据模型之上,称为 App,然后创建 QuestionsCollectioncurrent_question_id 此模型的属性。然后我们会在路由器方法中更新这个current_question_id attr。

    现在我们真的在做饭,我们的应用程序状态不仅持久化在浏览器的 URL 中,而且还作为可观察对象存在于应用程序层。我们可以轻松地创建一个ButtonsPanelView,它通过这个App 模型并在单击其按钮时触发正确的路由。在App 模型中实现hasNextQuestionhasPreviousQuestion 并将其用于toggle 或在用户无法后退或前进时禁用相应的按钮也很简单。

    按要求编辑:

    创建一个高于一切的App 模型非常简单。您可能已经在某处有如下代码:

    window._qs = new Questions();
    window._qs.fetch();
    

    只需这样做:

    var qs = new Questions();
    window.app = new App({questions: qs});
    qs.fetch();
    

    现在Questions 集合是应用模型的一个属性,正如我们想要的那样。那么App 的定义是什么?同样,有很多方法可以解决这个问题,但我喜欢使用Backbone.Models's validate 来确保我不会陷入糟糕的状态。以下是我可能会做的:

    App = Backbone.Model.extend({
    
       defaults: {
          current_question_index: 0
       },
    
       validate: function(attrs) {
    
          if(typeof attrs.current_question_index !== "undefined") {
             // we are trying the change the question index,
             // so make sure it is valid
             var len = this.get("questions").length
             if(attrs.current_question_index < 0 || attrs.current_question_index >= len) {
                // returning anything prevents invalid set
                return "index is out of bounds"; 
             }
          }
        },
    
        hasNextQ: function() {
          var next_ind = this.get("current_question_index") + 1;
          // use the logic we already created, in validate() but
          // convert it to a bool. NOTE in javascript:
          //       !"stuff"   === false
          //       !undefined === true 
          return !this.validate({current_question_index: next_ind}); 
        },
    
        nextQ: function() {
          var next_ind = this.get("current_question_index") + 1;
          // validate() will prevent us from setting an invalid index
          return this.set("current_question_index", next_ind);
    
        }
    
    });
    

    【讨论】:

    • 如果我可以提出建议,我已经看到称为索引视图的集合级视图。因此,QuestionsView 可能是QuestionIndexView,这在视觉上与QuestionView 更加不同。否则我同意你的观点,并补充说 Backbone 的多种做事方式有时会让人感到不知所措
    • 我将其更新为QuestionsIndexView。就压倒性而言,我同意它在第一次学习时会有点棘手,但我认为当你想做一些与众不同的事情时,它会带来更多功能的回报。还有其他一些框架强加了更严格的架构,因此更加一致。恕我直言Emberjs 是一个例子
    • @Mathew,你的回答很棒。它确实对此有所了解!我希望这不是要求太多,但您能否详细说明如何制作“存在于所有数据之上的模型”。这正是我被困的地方。我有 n 个问题,我知道我会从 0 开始,但是每当用户单击“下一个”或上一个并相应地更新我的视图时,我想将该索引移动到 +1 和 -1。这就是我使用backbone.js的原因!非常感谢!
    • @fedeisas 当然,看看我最近的编辑,我只在一个方向上做了(下一个),但以前的想法是一样的
    【解决方案2】:

    正如我在 BackboneJS 中所理解的,“模型”是一个数据单元。例如,“待办事项”的单元数据将包含:

    • 日期
    • 一条消息
    • 状态

    这些数据单元存储在一个“集合”中。它们是包含“行”的“数据库表”的同义词。但是模型数据并不局限于像一行那样的二维。然后Backbone“视图”执行逻辑以及与界面交互 - 更像是“视图控制器”。视图包含事件处理程序、添加和删除元素的代码、更改界面等。

    【讨论】:

    • 非常感谢您抽出宝贵时间。看来我更习惯于模型的服务器端定义(一个模型可以返回几行),所以这让我很困惑。谢谢!
    猜你喜欢
    • 2016-06-09
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 2012-07-16
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2013-01-25
    相关资源
    最近更新 更多