【问题标题】:Backbone.js - Is this button and event bound correctly?Backbone.js - 这个按钮和事件绑定正确吗?
【发布时间】:2011-12-14 23:40:07
【问题描述】:

我正在通过创建一个表视图和一个单独的行视图并尝试将行添加到表中来试验 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 元素.

我正在尝试将日志消息写入控制台,但按钮似乎没有触发该方法,我不知道为什么。

这是一天的结束,我的大脑被炸了,所以我很感激任何关于这个的指点。谢谢。

【问题讨论】:

    标签: javascript jquery backbone.js


    【解决方案1】:

    这是一个工作示例。我用使用 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>
    

    【讨论】:

    • 太棒了!谢谢,这肯定会给我一些学习的东西。一个问题,为什么要在创建实例时定义模型而不是在定义中?
    • @PhillipKregg 我不太清楚你的意思。可以举个例子吗?
    • 没关系,我现在看到该函数正在传递模型的一个实例。我看错了。再次感谢!
    【解决方案2】:

    这是因为您在 主干遍历了您的事件集合之后添加了&lt;button id='contact'&gt;

    当您创建主干视图时,delegateEvents 在幕后被调用。这是主干查看您的事件哈希并将所有内容连接起来的地方。修复任何一个:

    • 在创建视图之前附加&lt;button id='contact'&gt;

    • 或者渲染后手动调用主干的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?
      ...
    

    【讨论】:

    • 感谢您的建议 - 我尝试了您的代码,但按钮似乎仍然没有触发事件。我还将按钮放在初始化函数中,甚至将它从 javascript 中拉出并直接放在 DOM 中,以确保它在脚本之前加载。仍然没有运气。我会错过其他东西吗?
    • 如果你直接将它添加到 dom 你的选择器将不起作用。如果骨干按我的预期工作,那么所有这些选择器都应该与视图的 el 相关。您必须专门调用委托事件似乎也很奇怪。我已经更新了我的答案,以显示更多可能的事情。
    【解决方案3】:
            _(this.collection.models).each(function(contact) {
                appendContact(contact);
            }, this) 
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 2012-05-25
      • 1970-01-01
      • 2013-08-15
      相关资源
      最近更新 更多