在视图添加新DOM元素时,backbone.js单击事件未触发

时间:2015-07-01 11:11:00

标签: javascript backbone.js

我写了一个简单的程序来创建表单帖子。创建新帖子后,标题将添加到文档中,单击标题后,单击事件将起作用并显示警告。当我创建另一个帖子时,它的标题也会显示第一个帖子的标题,但是当点击时它们都没有弹出警报。

 var PostModel = Backbone.Model.extend({
            defaults: {
                "title": "",
                "postTxt":""
            }
        });

        <!-- Collection -->

        var PostCollection = Backbone.Collection.extend({
            url: '/UserPosts',
            model: PostModel
        });

        <!-- Views -->

        var PostModelView = Backbone.View.extend({
            model: new PostModel(),
            tagName: 'li',
            template: _.template($('#post-title').html()),
            initialize: function() {
                console.log('Initialized PostModelView........');
            },
            events: {
               'click a' : 'showAlert'
            },
            showAlert: function(){
                console.log('event');
                alert("You clicked : " + this.model.get('title'));
            },
            render: function() {
                console.log('Running render() of PostModelView.....');
                var htmloutput = this.template(this.model.toJSON());
                this.$el.html(htmloutput);
                return this;
            }
        });

        var postmodelview = new PostModelView();
        var postcollection = new PostCollection();

        var PostCollectionView = Backbone.View.extend({
            collection: postcollection,
            tagName: 'ul',
            initialize: function() {
                console.log('Initialized PostCollectionView .......');
                this.collection.on('add', this.render, this);
                this.collection.on('remove', this.render, this);
                console.log('postcollectionview $el: ' + this.$el.html());
            },

            render: function() {


              this.collection.each(function(postmodel) {
                  console.log(JSON.stringify(postmodel));
                  var postmodelview = new PostModelView({model: postmodel});
                  console.log(JSON.stringify(postmodelview));
                  //var htmlout = postmodelview.render().$el;
                   var htmlout = this.$el.append(postmodelview.render().$el);
                  $('#postcontainer').html('');
                  $('#postcontainer').append(htmlout);
                  //this.$el.append(htmlout);

              },this);

              return this;

            }
        });



        function createPost() {

            var postcollectionview = new PostCollectionView();
            console.log('running creatPost()');
            var postmodel = new PostModel({ title: $('#title').val(), postTxt: $('#postTxt').val() });
            postcollection.create(postmodel);
            console.log("postcollection: " + JSON.stringify(postcollection.toJSON()));
             $('#title').val(''); //clears the input field
             $('#postTxt').val(''); // clears the input field

       }

1 个答案:

答案 0 :(得分:2)

让我们仔细看看:

var htmlout = this.$el.append(postmodelview.render().$el);
$('#postcontainer').html('');
$('#postcontainer').append(htmlout);
与大多数jQuery函数一样,

append返回其接收器,因此htmloutthis.$el。这意味着您要反复清除#postcontainer的内容并将this.$el重新加入其中。

html('')做什么?来自fine manual

  

.html()用于设置元素的内容时,该元素中的任何内容都将被新内容完全替换。此外,在使用新内容替换这些元素之前,jQuery 会从子元素中删除其他构造(如数据和事件处理程序)。

强调我的。所以每次你:

$('#postcontainer').html('');

您要从#postcontainer的孩子中删除所有事件处理程序,尤其是您要从this.$el删除所有事件。

你不应该做以下任何一件事:

$('#postcontainer').html('');
$('#postcontainer').append(htmlout);

该视图应该只是将子视图添加到其el并让调用者将其el放在页面的某个位置:

render: function() {
    this.collection.each(function(postmodel) {
        var postmodelview = new PostModelView({model: postmodel});
        this.$el.append(postmodelview.render().$el);
    }, this);
    return this;
}

然后在来电者中:

var postcollectionview = new PostCollectionView();
//...
#('#postcontainer').append(postcollectionview.render().el);

其他各种问题:

  1. 在视图的原型上设置model属性:

    var PostModelView = Backbone.View.extend({
        model: new PostModel(),
    

    没有多大意义。视图的每个实例通常都有自己的model,并且应该在实例化视图时提供。

  2. 同样,在视图上设置collection属性:

    var PostCollectionView = Backbone.View.extend({
        collection: postcollection,
    

    在实例化视图时,通常会设置collection

    var v = new PostCollectionView({ collection: post collection });
    
  3. 您在不同的范围内有两个不同的postmodelview变量,最高级别的变量几乎肯定是错误的。

  4. 您在createPost底部使用labels但标签在该上下文中没有任何意义,我想您的意思是这样说:

    $('#title').val('');   // clears the input field
    $('#postTxt').val(''); // clears the input field
    
  5. 演示:https://jsfiddle.net/ambiguous/tqdf2j0v/