骨干。js链接模型和视图

时间:2022-07-12 01:27:07

I have a table like this

我有一张这样的桌子。

<table>
  <tr id="row-one" class="item-row">
    <td class="price"></td>
    <td><input type="text" class="quantity" value="" /></td>
  </tr>
  <tr id="row-two" class="item-row">
    <td class="price"></td>
    <td><input type="text" class="quantity" value="" /></td>
  </tr>
  <tr id="subtotal">
    <td id="subtotal"></td>
    <td id="subquantity"></td>
  </tr>
</table>

That I am manipulating with this backbone js code

我正在处理这个主js代码

<script type="text/javascript">
  jQuery(document).ready(function($){
    var Item = Backbone.Model.extend({
      initialize: function(){
      },
      defaults: {
        price: 0,
        quantity: 0
      }
    });
    var ItemsCollection = Backbone.Collection.extend({
      model : Item,
      subquantity: function(){
        subquantity = 0;
        this.each(function(item){
          subquantity += item.get('quantity');
        });
        return subquantity;
      }
    });
    var ItemView = Backbone.View.extend({
      events: {
        "change .quantity": "updateQuantity"
      },
      render: function(){
        alert('render');
      },
      updateQuantity: function(){
        this.model.set({quantity: this.$('.quantity').val()});
        console.log(this.model.get('quantity'));
      }
    });
    var totals = new ItemsCollection();
    var item_one = new Item({ price:1,quantity:10 });
    var item_two = new Item({ price:1,quantity:20 });
    totals.add(item_one);
    totals.add(item_two);
    var view_one = new ItemView({model:item_one,el:'.item-row'});
  })
</script>

My questions are.

我的问题是。

1) So far I can manage one row, that's fine. But then I want to manage the second row. Do I just instantiate another instance of ItemView? Or can I use one ItemView instance to manage multiple Models? Or better yet, with the Collection

到目前为止,我只能排一行,没问题。然后我想管理第二行。我是否只是实例化了ItemView的另一个实例?或者,我可以使用一个ItemView实例来管理多个模型吗?或者更好的是,收藏

2) I am using the Collection to manage the subtotals and subquantity. Do I create a separate view to manage those fields in the DOM? Or should I just update them inside the collection?

2)我正在使用集合来管理小计和小数量。我是否要创建一个单独的视图来管理DOM中的这些字段?还是应该在集合中更新它们?

If anyone has any other tips I would love to hear it. This is my first time with backbone, so I just want as much info as possible. Thanks!

如果有人有其他的建议,我很乐意听。这是我第一次使用主干,所以我只想要尽可能多的信息。谢谢!

1 个解决方案

#1


14  

As with most Backbone questions, there isn't a "right" answer to this - you'll need to figure out the approach that works best for you, which will depend in part on how complex your application is likely to get.

与大多数主干问题一样,对于这个问题没有一个“正确”的答案——您需要找出最适合您的方法,这在一定程度上取决于您的应用程序可能会有多复杂。

The main thing that seems odd to me in your setup is that you've hard-coded your table to list two items - my guess is that, if you're using Backbone to begin with, you probably will be pulling a list of items from the server via AJAX and then populating the table with that list. In that case, usually you'd actually create the DOM for each row in the ItemView class:

的主要事情似乎很奇怪我在你设置的是你硬编码表列出两项——我猜,如果你使用骨干一开始,你可能会通过AJAX从服务器拉的项目列表,然后填充的表列表。在这种情况下,通常会为ItemView类中的每一行创建DOM:

var ItemView = Backbone.View.extend({
  // there are many different ways to do this, here's one
  tagName: 'tr',
  className: 'item-row',
  // make an Underscore template for the inner HTML
  template: _.template(
    '<td class="price"><%= price %></td>' +
        '<td><input type="text" class="quantity" value="<%= quantity %>" /></td>'
  ),
  render: function(){
    // this.el is already set to a tr.item-row DOM element
    $(this.el).html(
        // fill in the template with model attributes
        this.template(this.model.toJSON())
    );
    // allows chaining
    return this;
  }
  // ... now your events and handler as written
});

This gives you an ItemView which, when rendered, has the rendered element you want to insert available once you call .render(). Depending on your setup, you might call this.render() right away in an initialize() function, or you might fetch more data asynchronously and then call render() in the callback. Either way, you have one view instance tied to one model. To manage multiple models, I might have another View class to hold the collection, which would be responsible for instantiating child ItemView instances:

这将为您提供一个ItemView,在呈现时,其中包含您希望在调用.render()之后插入的已呈现元素。根据您的设置,您可以在initialize()函数中立即调用this.render(),也可以异步获取更多数据,然后在回调中调用render()。无论哪种方式,都将一个视图实例绑定到一个模型。为了管理多个模型,我可能有另一个视图类来保存集合,它将负责实例化子ItemView实例:

var ItemsView = Backbone.View.extend({
    el: '#myTable',
    render: function() {
        var tableView = this;
        // instantiate and render children
        this.collection.each(function(item) {
            var itemView = new ItemView({ model: item });
            $(tableView.el).append(itemView.render().el);
        });
    }
});

Then in the main body of your code, all you need to do is pass the collection to your parent view, and render it:

然后在代码主体中,您需要做的就是将集合传递给父视图,并呈现它:

var tableView = new ItemsView({ collection: totals });

There's a lot more to add here, most of it dealing with asynchronously fetching, rendering, and refreshing data from the server, but hopefully this gives you a basic idea of the approach. Again, however, I should emphasize that this is just one way to do things - you could, for example, build the same app with only the ItemsView class, making it responsible for rendering all of the items itself. But the approach of using one view to manage the collection plus child views to manage the models keeps things nicely separate, and helps to minimize complexity as your app gets bigger.

这里还有很多要添加的内容,其中大部分涉及异步获取、呈现和从服务器刷新数据,但希望这能让您对该方法有一个基本的了解。但是,我要再次强调,这只是一种方法—例如,您可以只使用ItemsView类构建相同的应用程序,使其负责呈现所有项本身。但是,使用一个视图来管理集合和子视图来管理模型的方法可以很好地分离事物,并有助于在应用变得更大时最小化复杂性。

#1


14  

As with most Backbone questions, there isn't a "right" answer to this - you'll need to figure out the approach that works best for you, which will depend in part on how complex your application is likely to get.

与大多数主干问题一样,对于这个问题没有一个“正确”的答案——您需要找出最适合您的方法,这在一定程度上取决于您的应用程序可能会有多复杂。

The main thing that seems odd to me in your setup is that you've hard-coded your table to list two items - my guess is that, if you're using Backbone to begin with, you probably will be pulling a list of items from the server via AJAX and then populating the table with that list. In that case, usually you'd actually create the DOM for each row in the ItemView class:

的主要事情似乎很奇怪我在你设置的是你硬编码表列出两项——我猜,如果你使用骨干一开始,你可能会通过AJAX从服务器拉的项目列表,然后填充的表列表。在这种情况下,通常会为ItemView类中的每一行创建DOM:

var ItemView = Backbone.View.extend({
  // there are many different ways to do this, here's one
  tagName: 'tr',
  className: 'item-row',
  // make an Underscore template for the inner HTML
  template: _.template(
    '<td class="price"><%= price %></td>' +
        '<td><input type="text" class="quantity" value="<%= quantity %>" /></td>'
  ),
  render: function(){
    // this.el is already set to a tr.item-row DOM element
    $(this.el).html(
        // fill in the template with model attributes
        this.template(this.model.toJSON())
    );
    // allows chaining
    return this;
  }
  // ... now your events and handler as written
});

This gives you an ItemView which, when rendered, has the rendered element you want to insert available once you call .render(). Depending on your setup, you might call this.render() right away in an initialize() function, or you might fetch more data asynchronously and then call render() in the callback. Either way, you have one view instance tied to one model. To manage multiple models, I might have another View class to hold the collection, which would be responsible for instantiating child ItemView instances:

这将为您提供一个ItemView,在呈现时,其中包含您希望在调用.render()之后插入的已呈现元素。根据您的设置,您可以在initialize()函数中立即调用this.render(),也可以异步获取更多数据,然后在回调中调用render()。无论哪种方式,都将一个视图实例绑定到一个模型。为了管理多个模型,我可能有另一个视图类来保存集合,它将负责实例化子ItemView实例:

var ItemsView = Backbone.View.extend({
    el: '#myTable',
    render: function() {
        var tableView = this;
        // instantiate and render children
        this.collection.each(function(item) {
            var itemView = new ItemView({ model: item });
            $(tableView.el).append(itemView.render().el);
        });
    }
});

Then in the main body of your code, all you need to do is pass the collection to your parent view, and render it:

然后在代码主体中,您需要做的就是将集合传递给父视图,并呈现它:

var tableView = new ItemsView({ collection: totals });

There's a lot more to add here, most of it dealing with asynchronously fetching, rendering, and refreshing data from the server, but hopefully this gives you a basic idea of the approach. Again, however, I should emphasize that this is just one way to do things - you could, for example, build the same app with only the ItemsView class, making it responsible for rendering all of the items itself. But the approach of using one view to manage the collection plus child views to manage the models keeps things nicely separate, and helps to minimize complexity as your app gets bigger.

这里还有很多要添加的内容,其中大部分涉及异步获取、呈现和从服务器刷新数据,但希望这能让您对该方法有一个基本的了解。但是,我要再次强调,这只是一种方法—例如,您可以只使用ItemsView类构建相同的应用程序,使其负责呈现所有项本身。但是,使用一个视图来管理集合和子视图来管理模型的方法可以很好地分离事物,并有助于在应用变得更大时最小化复杂性。