Backbone.js - 此按钮和事件是否正确绑定?

时间:2011-12-14 23:40:07

标签: javascript jquery backbone.js

我正在通过创建表视图和单独的行视图并尝试将行添加到表中来试验Backbone.js:

enter image description here

我有:

  • 联系模式
  • 联系人集合
  • 联系人视图(充当 主要观点)
  • ContactRow视图

到目前为止,该项目工作正常 - 除了一个应该触发添加行的函数的按钮。

到目前为止,这是我的代码:

$(function($) {

    window.Contact = Backbone.Model.extend({
        defaults: {
            first_name: "John",
            last_name: "Smith",
            address: "123 Main St"
        }
    }); 


    window.Contacts = Backbone.Collection.extend({
        model: Contact
    }); 



    window.ContactRow = Backbone.View.extend({
        //el: $("#contacts-table table tbody"),     

        row_template: _.template($("#contact-row").html()),

        initialize: function() {
            _.bindAll(this, "render")
        },

        render: function() {
            $("tbody").html("<tr><td>Look at me, I'm a row!</td></tr>");
            return this;
        }
    }); 


    window.ContactsView = Backbone.View.extend({        
        el: $("#contacts-container"),   

        events: {
            "click button#add_contact": "addContact"
        },

        template: _.template($("#contacts-table").html()),

        initialize: function() {
            _.bindAll(this, "render", "addContact", "appendContact");   

            this.collection = new Contacts();
            this.collection.bind("add", this.appendContact);

            var contactRow = new ContactRow();          
            this.render();
            this.appendContact(); // Just a test to see if the function is working
        },

        render: function() {
            $("#button-container").append("<button id='add_contact'>Add Contact</button>");
            $(this.el).html(this.template);
            _(this.collection.models).each(function(contact) {
                appendContact(contact);
            }, this)            
        },

        addContact: function() {
            console.log("yup, it works!"); // well, not yet
            var contact = new Contact();
            this.collection.add(contact);               

        },

        appendContact: function(contact) {
            var contactRow = new ContactRow({
                model: contact
            });

            $("body").append(contactRow.render().el);
        }

    });

     var contactsView = new ContactsView(); 

}, jQuery);

正如您所看到的,我有一个 addContact 函数,该函数与“添加联系人”按钮的单击事件相关联,该按钮在渲染过程中被附加到主页上的div元素

我正在尝试将日志消息写入控制台,但该按钮似乎没有触发该方法,我无法弄清楚原因。

这是一天的结束,我的大脑是油炸的,所以我很欣赏这方面的任何指示。感谢。

3 个答案:

答案 0 :(得分:2)

这是因为您在 骨干已遍历您的事件集合后附加<button id='contact'>

创建骨干视图时,会在后台调用delegateEvents。这是骨干查看您的事件哈希并将所有内容连接起来的地方。修复Either:

  • 在创建视图之前附加<button id='contact'>

  • 或在呈现后手动调用主干delegateEvents

所以你的渲染功能可能如下:

render: function() {
    $("#button-container").append("<button id='add_contact'>Add Contact</button>");
    $(this.el).html(this.template);
    this.delegateEvents(); // re-wire events matching selectors in the event hash
    _(this.collection.models).each(function(contact) {
        appendContact(contact);
    }, this)
    return this; // you should also do this so you can chain         
},

<强>更新

你必须手动拨打delegateEvents似乎很奇怪。也可能是#button-contianer不是视图el的子项。该事件哈希中的所有选择器都限定为el,因此如果#button-contianer不是它的子项,则button#add_contact选择器将永远不会找到任何内容。作为概念证明,请尝试以下方法:在渲染方法中:

render: function() {
  console.log($(this.el).find("button#add_contact").length) // get anything?
  ...

答案 1 :(得分:2)

这是一个有效的例子。我使用Backbone的最佳实践更新了代码。

注意我没有通过Backbone视图添加按钮。该按钮是html正文的一部分,我只是订阅了它的点击事件,然后将联系人添加到联系人集合。

<html>
  <head>
    <script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'></script>
    <script type='text/javascript' src='http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.4/underscore-min.js'></script>
    <script type='text/javascript' src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js'></script>
    <script type='text/javascript'>
      $(function() {
        //initialize the contacts collection and add some contacts
        contacts = new Contacts();
        contacts.add(new Contact());
        contacts.add(new Contact());

        //only need to render the ContactsView once
        var view = new ContactsView({ collection: contacts });
        $("body").append(view.render().el);

        //adding a contact to the contacts list when the
        //button is clicked
        $("#add-contact").click(function() {
          contacts.add(new Contact());
        });
      });

      Contact = Backbone.Model.extend({
        defaults: {
          first_name: "John",
          last_name: "Smith",
          address: "123 Main St"
        }
      }); 

      Contacts = Backbone.Collection.extend({
        model: Contact
      }); 

      ContactRow = Backbone.View.extend({
        initialize: function() {
          _.bindAll(this, "render");
          this.template = _.template($("#contact-row").html());
        },

        //every backbone view has a tagName. the default tagName is 'div'
        //we're changing it to a table row
        tagName: 'tr',

        render: function() {
          $(this.el).html(this.template(this.model.toJSON()));
          return this;
        }
      }); 

      ContactsView = Backbone.View.extend({        
        initialize: function() {
          _.bindAll(this, "render");
          this.headerTemplate = $("#contacts-table-header").html();
          this.collection.bind("add", this.renderContact, this);
        },

        //the ContactsView element will be a table
        tagName: 'table',

        render: function() {
          $(this.el).html(this.headerTemplate);

          this.collection.each(function(contact) {
            this.renderContact(contact);
          }, this);

          return this;
        },

        renderContact: function(contact) {
          var contactView = new ContactRow({ model: contact });
          $(this.el).append(contactView.render().el);
        }
      });

    </script>

    <script type='text/template' id='contact-row'>
      <td><%= first_name %></td>
      <td><%= last_name %></td>
      <td><%= address %></td>
    </script>

    <script type='text/template' id='contacts-table-header'>
      <thead>
        <th>First Name</th>
        <th>Last Name</th>
        <th>Address</th>
      </thead>
    </script>
  </head>
  <body>
    <button id="add-contact">Add Contact</button>
  </body>
</html>

答案 2 :(得分:0)

        _(this.collection.models).each(function(contact) {
            appendContact(contact);
        }, this) 

此代码无效,因为您没有名为appendContact的变量。应该是:

        _(this.collection.models).each(this.appendContact(contact), this);