我的第一个骨干模型/视图。我走在正确的轨道上吗?

发布于 2024-12-23 17:15:20 字数 5407 浏览 1 评论 0原文

目标是构建一个 UI 来选择 T 恤的品牌、尺寸和颜色。并非所有颜色都适用于每种尺码,也并非所有尺码/颜色都适用于每种品牌。

所以基本的 UI 是三个选择元素:品牌、尺寸和颜色。

在阅读了一堆教程后,我首先创建了品牌、尺寸和颜色的模型,以及品牌、尺寸、颜色的集合,以及每个模型的视图,并编写了连接它们的代码……有点失去了理智。

第二次尝试是在这里,我创建了一个“Config”模型和一个“Config”视图。模型作为当前品牌、尺寸和颜色的属性,以及当前可选择的品牌、型号和颜色的属性。

作为一名经验丰富的backbone.js 专家,您会采用这种方式吗?

这是模型。基本上,我“手动”处理在 setMake 方法中获取正确的尺寸/颜色,并在 setSize 方法中获取正确的颜色,然后在模型上设置必要的更改。

var design_id = 2; // set server-side

var ConfigModel = Backbone.Model.extend({

    initialize: function(){
      this.baseUrl = "/designs/" + design_id + "/configure/";
    },

    setMake: function(make_id){
      var me = this;
      var make = _.find(this.get("makes"), function(el){ 
                  return el.id == make_id });
      // aggregate changes to the model:         
      var changes = {
        "make": make
      };
      // get current make/size/color:
      var cur_make_id = make.id;
      var cur_size_id = this.get("size").id;
      var cur_color_id = this.get("color").id;

      // get sizes for the current make:
      $.getJSON(me.baseUrl + "makes/" + cur_make_id + "/sizes/",
           function(data){
            changes.sizes = data;
            if(!_.find(data, function(el){ 
                  return el.id == cur_size_id })){
            // the currently selected size is not available, 
            // so use the first size
            changes.size = data[0];
            cur_size_id = changes.size.id;
          }
        // and get the colors for the current make and size:
        $.getJSON(me.baseUrl + "makes/" + cur_make_id 
               + "/sizes/" + cur_size_id + "/colors/",
             function(data){
               changes.colors = data;
               if(!_.find(data, 
                      function(el){ 
                         return el.id == cur_color_id })){
                          // the currently selected color 
                          // is not available, 
                          //so use the first one in the list
                     changes.color = data[0];
                       }
                me.set(changes);
              });
         });
      },

    setSize: function(size_id){
      // retrieve colors for the new size
      var me = this;
      var size = _.find(this.get("sizes"), 
              function(el){ return el.id == size_id });
      var changes = {
        "size": size
      };

      var cur_make_id = this.get("make").id;
      var cur_size_id = size.id;
      var cur_color_id = this.get("color").id;

      $.getJSON(me.baseUrl + "makes/" + cur_make_id + 
                "/sizes/" + cur_size_id + "/colors/",
          function(data){
             changes.colors = data;
             if(!_.find(data, 
                function(el){ 
                  return el.id == cur_color_id })){
             changes.color = data[0];
          }
          me.set(changes);
      });
    },

    setColor: function(color_id){
      var color = _.find(this.get("colors"), 
             function(el){ 
                return el.id == color_id });
      this.set({"color": color});
    }
  });

这是模型实例。初始默认值是在服务器端设置的:

  var Config = new ConfigModel({
    design_id: 2,

    make: {"id": 1, "name": "Men's Organic Cotton Tee"},
    size: {"id": 4, "name": "L"},
    color: {"id": 2, "name": "Black"},

    makes: [{"id": 2, "name": "Women's Organic Cotton Tee"}, 
            {"id": 1, "name": "Men's Organic Cotton Tee"}],
    sizes: [{"id": 2, "name": "S"}, 
            {"id": 3, "name": "M"}, 
            {"id": 4, "name": "L"}],
    colors:  [{"id": 2, "name": "Black"},  
             {"id": 3, "name": "red"}]

  });

这是视图。我认为这非常简单。绑定到选择元素上的更改事件并在模型上调用 setMake 或 setSize,然后侦听来自模型的更改事件:

var ConfigView = Backbone.View.extend({
        el: $("#config"),

        optionsTemplate: _.template($("#options-template").html()),

        events:{
          "change #make select": "onChangeMake",
          "change #size select": "onChangeSize",
          "change #color select": "onChangeColor"
        },

        initialize: function(){
          Config.bind("change:makes", this.updateMakes, this);
          Config.bind("change:sizes", this.updateSizes, this);
          Config.bind("change:colors", this.updateColors, this);
        },

        render: function(){
        //console.log("ConfigureView.render");
        this.updateSelect("make");
        this.updateSelect("size");
        this.updateSelect("color");
        },

        updateMakes: function(){ 
          this.updateSelect("make");
        },

        updateSizes: function(){ 
          this.updateSelect("size"); 
        },

        updateColors: function(){ 
          this.updateSelect("color"); 
        },

        updateSelect: function(which){
          // updates the select specified by "which"
          this.$("#" + which + " select").html(this.optionsTemplate({
            chosen:Config.get(which),
            options:Config.get(which + "s")
          }));
        },

        onChangeMake: function(){
        Config.setMake(this.$("#make select").val());
        },

        onChangeSize: function(){
        Config.setSize(this.$("#size select").val());
        },

        onChangeColor: function(){
          Config.setColor(this.$("#color select").val());
        }
    });

    var app = new ConfigView();
    app.render();

The goal is to build a UI to select a make, size, and color for a T-shirt. Not all colors are available for every size, and not all sizes/colors are available for every make.

So the basic UI is three select elements for make, size, and color.

After reading a bunch of tutorials, I started out by creating models for Make, Size, and Color, and collections for Makes, Sizes, Colors, and views for each, and code to connect them.. and sort of lost my mind.

Second attempt is here, where I created a single "Confg" model, and a single "Config" view. The model as attributes for the current make, size, and color, and also attributes for the currently select-able makes, models, and colors.

Is this how you, you being a seasoned backbone.js expert, would have approached this?

Here's the model. Basically, I "manually" handle fetching correct sizes / colors in the setMake method, and correct colors in the setSize method, and then set the necessary changes on the model.

var design_id = 2; // set server-side

var ConfigModel = Backbone.Model.extend({

    initialize: function(){
      this.baseUrl = "/designs/" + design_id + "/configure/";
    },

    setMake: function(make_id){
      var me = this;
      var make = _.find(this.get("makes"), function(el){ 
                  return el.id == make_id });
      // aggregate changes to the model:         
      var changes = {
        "make": make
      };
      // get current make/size/color:
      var cur_make_id = make.id;
      var cur_size_id = this.get("size").id;
      var cur_color_id = this.get("color").id;

      // get sizes for the current make:
      $.getJSON(me.baseUrl + "makes/" + cur_make_id + "/sizes/",
           function(data){
            changes.sizes = data;
            if(!_.find(data, function(el){ 
                  return el.id == cur_size_id })){
            // the currently selected size is not available, 
            // so use the first size
            changes.size = data[0];
            cur_size_id = changes.size.id;
          }
        // and get the colors for the current make and size:
        $.getJSON(me.baseUrl + "makes/" + cur_make_id 
               + "/sizes/" + cur_size_id + "/colors/",
             function(data){
               changes.colors = data;
               if(!_.find(data, 
                      function(el){ 
                         return el.id == cur_color_id })){
                          // the currently selected color 
                          // is not available, 
                          //so use the first one in the list
                     changes.color = data[0];
                       }
                me.set(changes);
              });
         });
      },

    setSize: function(size_id){
      // retrieve colors for the new size
      var me = this;
      var size = _.find(this.get("sizes"), 
              function(el){ return el.id == size_id });
      var changes = {
        "size": size
      };

      var cur_make_id = this.get("make").id;
      var cur_size_id = size.id;
      var cur_color_id = this.get("color").id;

      $.getJSON(me.baseUrl + "makes/" + cur_make_id + 
                "/sizes/" + cur_size_id + "/colors/",
          function(data){
             changes.colors = data;
             if(!_.find(data, 
                function(el){ 
                  return el.id == cur_color_id })){
             changes.color = data[0];
          }
          me.set(changes);
      });
    },

    setColor: function(color_id){
      var color = _.find(this.get("colors"), 
             function(el){ 
                return el.id == color_id });
      this.set({"color": color});
    }
  });

Here's the model instance. The initial defaults are set server-side:

  var Config = new ConfigModel({
    design_id: 2,

    make: {"id": 1, "name": "Men's Organic Cotton Tee"},
    size: {"id": 4, "name": "L"},
    color: {"id": 2, "name": "Black"},

    makes: [{"id": 2, "name": "Women's Organic Cotton Tee"}, 
            {"id": 1, "name": "Men's Organic Cotton Tee"}],
    sizes: [{"id": 2, "name": "S"}, 
            {"id": 3, "name": "M"}, 
            {"id": 4, "name": "L"}],
    colors:  [{"id": 2, "name": "Black"},  
             {"id": 3, "name": "red"}]

  });

And here's the view. I think this is pretty straighforward.. bind to change events on the select elements and call setMake or setSize on the model, and then listen for change events from the model:

var ConfigView = Backbone.View.extend({
        el: $("#config"),

        optionsTemplate: _.template($("#options-template").html()),

        events:{
          "change #make select": "onChangeMake",
          "change #size select": "onChangeSize",
          "change #color select": "onChangeColor"
        },

        initialize: function(){
          Config.bind("change:makes", this.updateMakes, this);
          Config.bind("change:sizes", this.updateSizes, this);
          Config.bind("change:colors", this.updateColors, this);
        },

        render: function(){
        //console.log("ConfigureView.render");
        this.updateSelect("make");
        this.updateSelect("size");
        this.updateSelect("color");
        },

        updateMakes: function(){ 
          this.updateSelect("make");
        },

        updateSizes: function(){ 
          this.updateSelect("size"); 
        },

        updateColors: function(){ 
          this.updateSelect("color"); 
        },

        updateSelect: function(which){
          // updates the select specified by "which"
          this.$("#" + which + " select").html(this.optionsTemplate({
            chosen:Config.get(which),
            options:Config.get(which + "s")
          }));
        },

        onChangeMake: function(){
        Config.setMake(this.$("#make select").val());
        },

        onChangeSize: function(){
        Config.setSize(this.$("#size select").val());
        },

        onChangeColor: function(){
          Config.setColor(this.$("#color select").val());
        }
    });

    var app = new ConfigView();
    app.render();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

月牙弯弯 2024-12-30 17:15:20

有些东西告诉我你的 $.getJSON 函数应该是 Backbone Collections。

http://documentcloud.github.com/backbone/#Collection

使用集合而不是集合您所做的将使您的应用程序更易于阅读和管理。还使用 $.getJSON 而不是骨干的集合类型远离骨干的唯一模型。

这实际上是我不久前在 StackOverflow 上发布的一个问题,它可能与我所说的有关。看看朱利安怎么说。

将 JSON feed 与 Backbone JS 集成

Something tells me that your $.getJSON functions should instead be Backbone Collections.

http://documentcloud.github.com/backbone/#Collection

Using collections instead of what you're doing will make your application easier to read and manage. Also using $.getJSON instead of backbone's collection kind of steers away from backbone's sole model.

Here is actually a question I posted not too long ago on StackOverflow which might relate to what I'm saying. Look at what Julien had to say.

Integrating JSON feed with Backbone JS

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文