主干-从模板中迭代的集合中获取特定的模型

Backbone - Get a certain model from a collection that is iterated in a template

本文关键字:集合 获取 模型 迭代 主干      更新时间:2023-09-26

假设我的模板如下所示:

<script type="text/template" id="template">
    {{#each []}}
    <div>{{this.id}}</div>
    <div>{{this.name}}</div>
    <div>{{this.description}}</div>
    <input id="my-btn" type="button">Button</input>
    {{/each}}
</script>

模型和集合:

var Item = Backbone.Model.extend({
    defaults: {
        id: null,
        name: '',
        description: ''
    }
});
var ItemCollection = Backbone.Collection.extend({
    model: Item,
    url: function() {
        return '/items';
    }
});

在视图中,我只是提取项目并显示它们:

var ItemsView = Backbone.View.extend({
    el: $('#items'),
    template: Handlebars.compile($('#template').html()),
    items: new ItemCollection(),
    initialize: function() {
        var self = this;
        this.items.fetch({success: function() {
            self.render();
        }});
    },
    render: function() {
        var items = new ItemCollection();
        var html = this.template(items.toJSON());
        this.$el.html(html);
    }
});

模板中每个包含其字段的项目都有自己的按钮。

现在,我需要添加一个功能,该功能将在按下模板中的按钮时触发,因此单击某个功能必须获取与模板中按钮关联的项目。

我该怎么做?

这里有一种方法可以实现您的要求——只需在events散列中添加一个点击处理程序(http://backbonejs.org/#View-事件)。我为按钮添加了数据短划线属性,以便在单击处理程序中可以确定要对哪个按钮/模型执行操作。

var ItemView = window.Backbone.View.extend({
    tagName: 'div',
    template: Handlebars.compile($('#template').html()),
    events: {
            'click .item-btn': 'clickHandler'
    },
    render: function() {
      this.$el.html(this.template({
        items: collection.toJSON()
      }));
      return this; // backbone convention -- return the view
    },
    clickHandler: function(e) {
           alert($(e.target).data().itemId + ' clicked');
    }
  });

以上视图假设以下模板:

<script type="text/template" id="template">
      {{#each items}}
      <div>{{this.id}}</div>
      <div>{{this.name}}</div>
      <div>{{this.description}}</div>
      <input class="item-btn" data-item-id="{{this.id}}" type="button" value="Button {{this.id}}"></input>
      {{/each}}
    </script>

以下是一个工作演示:https://jsfiddle.net/9cgzcc3y/

实现这一点的另一种方法(也是我个人更喜欢的方法)是为每个模型创建一个单独的视图。这样,每个视图都将由一个单独的模型支持。

var ItemView = window.Backbone.View.extend({
    tagName: 'div',
    template: Handlebars.compile($('#template').html()),
    events: {
           'click .item-btn': 'clickHandler'
    },
    render: function() {
      this.$el.html(this.template(this.model.toJSON()));
      return this;
    },
    clickHandler: function() {
        alert('clicked: ' + this.model.get('id'));
    }
  });
  var ItemsView = window.Backbone.View.extend({
    tagName: 'div',
    initialize: function() {
      this.collection = collection;
    },
    render: function() {
        var frag = document.createDocumentFragment();
        this.collection.each(function(model) {
          frag.appendChild(new ItemView({model: model}).render().el);
        });
      this.$el.append(frag);
      return this;
    }
  });
  $('#items').append(new ItemsView().render().$el);

以下是此替代方案的工作演示:https://jsfiddle.net/45kuhp7h/