繁体   English   中英

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

[英]Backbone.js - Is this button and event bound correctly?

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

在此输入图像描述

我有:

  • 联系模式
  • 联系人集合
  • 联系人视图(充当主视图)
  • 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元素。

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

这是一天的结束,我的大脑是炒的,所以我很感激任何指针。 谢谢。

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

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

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

    要么

  • 或者在渲染后手动调用backbone的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不是它的子项,则button#add_contact选择器将永远不会找到任何内容。 作为概念证明,请尝试以下方法:在渲染方法中:

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

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

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

<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>
        _(this.collection.models).each(function(contact) {
            appendContact(contact);
        }, this) 

此代码不起作用,因为您没有名为appendContact的变量。 应该:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM