【问题标题】:Should Backbone Model represent a view or a server-side resource?Backbone Model 应该代表视图还是服务器端资源?
【发布时间】:2014-11-27 22:15:39
【问题描述】:

假设我有一个 Rails AR 模型如下

class User
  has_one :profile
end

class Profile
  belongs_to user
  has_one :address
end

class Address
  belongs_to :profile
end

并在客户端构建一个用户配置文件视图。现在,我的 Backbone 模型应该是什么样子?它应该复制它在 Rails/服务器端域模型中的方式吗?我们是否有明确的理由说明它必须这样,还是只是主观的?

感谢您的经验分享!

【问题讨论】:

    标签: ruby-on-rails backbone.js backbone-model


    【解决方案1】:

    通常,您的主干模型和集合应遵循您的 REST API(或任何其他客户端 服务器端通信)。

    1. 例如,如果这些 ruby​​ 模型通过 :

      传递到前端
      GET /api/user/:id
      

      你得到的回应是

      [{ profile: { address: "21st str." } },{ profile: { address: "17th str." } }]
      

      你需要一个模型

      User = Backbone.Model
      Users = Backbone.Collection.extend({
         model: User,
         url: "/api/user"
      });
      
    2. 但是,如果您在 API 中做一些更复杂的事情并且在 API 中有更多 url,您可以选择最适合您与前端客户端交互的结构。例如,如果您的网站根本不需要用户 api,而您使用这些 url 将数据传递到前端:

      GET /api/profile
      

      你只能有一个模型

      ProfileModel = Backbone.Model.extend({
          url: "/api/profile"
      })
      

      您可以轻松设置地址

      profile = new ProfileModel();
      profile.set('address', '21st str.');
      

    底线

    Backbone 通常应该遵循 REST API 的 URL 结构。如果您这样做,您将享受使用正确自动配置的 REST Ajax 调用(GET、POST、DELETE、PUT)的全部好处。

    通常我不做的是让我的 Backbone 应用程序结构遵循数据库架构。这可能会让人头疼,因为您需要创建一种方式,以便您的后端(Ruby 应用程序)能够提供与您正在使用的 ORM 几乎相同的数据库访问。

    【讨论】:

    • 经过一些技术讨论后,我们的团队决定采用这种方式,我正等着听社区中的其他人是如何做的。从今天的情况来看,或者在我们听到更好的解释之前,我将你的答案标记为正确答案。谢谢你的时间! -- 卡提克
    【解决方案2】:

    为了简单起见,我认为模型应该同时代表服务器端模型和客户端视图状态,通过前面的 _ 来区分视图状态属性。保存模型时,服务器会忽略视图状态属性。

    这是我使用的工作流程的简化示例:

    var animal = new View({
      initialize: function(){
        // define the model and default view state when view is initialized
        this.model = new Model({id:3, _edit:false}, {url:'/animals'));
      }
      , render: function(){
        var self = this;
        this.undelegateEvents();
        this.delegateEvents({
          'click [data-trgger]': function(e){
            self[$(e.currentTarget).attr('data-trigger')].apply(this);
          }
        });
        var success = function(){
          // pass the model to the template engine
          self.$el.html( _.template('#edit-animals', {model: self.model}) );
        }
        // fetch the model from the server when view is rendered
        // you could check if the model is already fetched
        this.model.fetch({success:success});
      }
      , onSave: function(){
        // save the model then:
        this.model.set('_edit', false);
        this.render();
      }
      , onEdit: function(){
        this.model.set('_edit', true);
        this.render();
      }
    });
    

    还有模板:

    <% if(model.get('_edit')){ %>
    
      <!-- the view is in 'edit' state, show input and save button -->
      <div>
        <input type="text" name="breed" class="form-control">
      </div>
      <button class="btn btn-primary" data-trigger="onSave">Save</button>
    
    <% }else{ %>
    
      <!-- the view is in 'read-only' state, show values and edit button -->
      <button class="btn btn-default" data-trigger="onEdit">Edit</button>
      <div>
        <%= model.get('breed') %>
      </div>
    
    <% } %>
    

    【讨论】:

    • 这对于一个小案例来说看起来不错。但我感觉它在我们有许多嵌套关联/组合的实际用例中变得复杂。也就是说,我很感激你的时间。谢谢! --Karthik
    猜你喜欢
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 2020-01-13
    • 2011-12-06
    • 2019-09-25
    • 2019-02-01
    • 2015-06-23
    • 2012-01-12
    相关资源
    最近更新 更多