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

backbone.js click event not firing when new DOM element is added by view

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

 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

       }

让我们仔细看看这个:

var htmlout = this.$el.append(postmodelview.render().$el);
$('#postcontainer').html('');
$('#postcontainer').append(htmlout);

append,像大多数 jQuery 函数一样,returns 它的接收者所以 htmloutthis.$el。这意味着您正在重复清除 #postcontainer 的内容并将 this.$el 放回其中。

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

When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.

强调我的。所以每次你:

$('#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
    

演示:https://jsfiddle.net/ambiguous/tqdf2j0v/