2016-02-11 123 views
1

我目前正在学习BackboneJs并试图理解Backbone如何处理事件。我有一个简单的物品清单,每个物品旁边都有一个delete按钮。我试图找出为什么点击事件(删除按钮)在控制台中注册,但该项目未被删除。这是我有什么:单击删除按钮时删除相应的项目。 BackboneJs

var Vehicle = Backbone.Model.extend(); 
var Vehicles = Backbone.Collection.extend({ 
    model: Vehicle 
}); 


/************* 
single view 
**************/ 
var VehicleView = Backbone.View.extend({ 
    tagName: 'li', 
    className: 'vehicle', 
    render: function() { 
     this.$el.html(this.model.get("title") + " Registration Number is: " + this.model.get("regiNum") + " <button class='delete-btn'>Delete</button>"); 
     this.$el.attr("id", this.model.id); 
     return this; 
    } 
}); 

/************* 
Collection View 
*************/ 
var VehiclesView = Backbone.View.extend({ 
    tagName: "ul", 
    initialize: function() { 
     this.model.on('remove', this.vehicleRemove, this); 
    }, 
    events: { 
     "click .delete-btn": "vehicleRemove" 
    }, 
    vehicleRemove: function(vehicle) { 
     this.$("li#" + vehicle.id).remove() // this is not working. the item is not being removed 
     console.log('Delete button clicked') // this is registered in the console log 
    }, 

    render: function() { 
     var self = this; 
     this.model.each(function(vehicle) { 
      var vehicleView = new VehicleView({ 
       model: vehicle 
      }); 
      self.$el.append(vehicleView.render().$el); 
     }) 
    } 
}); 


var vehicles = new Vehicles([ 
    new Vehicle({ 
     id: 1, 
     title: "Toyota", 
     regiNum: "453454624" 
    }), 
    new Vehicle({ 
     id: 2, 
     title: "Honda", 
     regiNum: "daf4526" 
    }), 
    new Vehicle({ 
     id: 3, 
     title: "Audi", 
     regiNum: "jlkjfa34" 
    }) 
]) 

var vehiclesView = new VehiclesView({ 
    el: "#container", 
    model: vehicles 
}); 
vehiclesView.render(); 

请帮助我或指向我的正确方向将不胜感激。

回答

1

由于您有一个项目视图,最好为其提供删除自身的功能。通过这种方式,您不必破解自己从DOM中读取内容的方式,即可根据点击的项目视图元素找到相关的模型。

此外,你应该使用Backbone.View的remove()方法,而不是jQuery的remove()方法,因为它安全去除的视图注册的骨干事件,以及调用jQuery的remove()从DOM删除元素。

你可以调用model.destroy()这将表明你的持久层去除模型并将其从集合中删除。由于在这个例子中你没有持久层,所以我在项目视图的模型上触发了一个自定义事件,该模型在集合中处理以从模型中移除模型(模型事件传播到它的集合)。

没有必要自己手动初始化集合中的模型,骨干自动执行它,这就是集合model属性的用途。

您应该使用某种模板引擎,而不是在视图中进行字符串处理以进行渲染,无论如何您都可以使用_.template()

此外,正如dskoda1已经提到的,你不应该通过骨干。使用model选项进行收集,模型和集合是Backbone.view将检测到的两个选项。即使它没有伤害,它仍然很混乱。

var Vehicle = Backbone.Model.extend(); 
 
var Vehicles = Backbone.Collection.extend({ 
 
    model: Vehicle, 
 
    initialize: function() { 
 
    this.on('delete', this.remove); 
 
    } 
 
}); 
 
var VehicleView = Backbone.View.extend({ 
 
    tagName: 'li', 
 
    className: 'vehicle', 
 
    template: _.template($('#vehicle-template').html()), 
 
    events: { 
 
    "click .delete-btn": "vehicleRemove" 
 
    }, 
 
    initialize: function() { 
 
    this.render(); 
 
    }, 
 
    render: function() { 
 
    this.$el.html(this.template(this.model.toJSON())); 
 
    return this; 
 
    }, 
 
    vehicleRemove: function(vehicle) { 
 
    this.remove(); 
 
    //this.model.destroy(); /* The collection should have a url */ 
 
    this.model.trigger('delete', this.model); 
 
    }, 
 
}); 
 
var VehiclesView = Backbone.View.extend({ 
 
    tagName: "ul", 
 
    initialize: function() { 
 
    this.render(); 
 
    }, 
 
    render: function() { 
 
    this.collection.each(function(vehicle) { 
 
     var vehicleView = new VehicleView({ 
 
     model: vehicle 
 
     }); 
 
     this.$el.append(vehicleView.$el); 
 
    }, this) 
 
    } 
 
}); 
 

 
var vehicles = new Vehicles([{ 
 
    id: 1, 
 
    title: "Toyota", 
 
    regiNum: "453454624" 
 
}, { 
 
    id: 2, 
 
    title: "Honda", 
 
    regiNum: "daf4526" 
 
}, { 
 
    id: 3, 
 
    title: "Audi", 
 
    regiNum: "jlkjfa34" 
 
}]); 
 

 
var vehiclesView = new VehiclesView({ 
 
    el: "#container", 
 
    collection: vehicles 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone-min.js"></script> 
 
<div id="container"></div> 
 
<script type="text/template" id="vehicle-template"> 
 
    <%=title%>Registration Number is: 
 
    <%=regiNum%> 
 
     <button class='delete-btn'>Delete</button> 
 
</script>

+0

非常感谢你的解释! –

-1

this.remove()

在这一点上,骨干已经知道你想删除哪个模型,所以不需要指定一个jQuery选择器。

当然,.remove()只会去掉DOM中的元素。你在寻找model.destroy(),它会发送一个DELETE命令给服务器吗?

+0

'this.remove()'的作品,但现在它删除所有三个项目被点击的按钮中的任何一个时。单击相应的删除按钮而不是所有项目时是否可以删除项目? 现在我只关心如何从DOM中删除元素,而不是从服务器中删除,但是感谢那条信息! –

1

您可能想要在按钮上使用的一个有用的atrribute将是data-id。将此值设置为模型ID可让您更干净地选择正确的删除模型。新的按钮HTML现在是:

"<button class='delete-btn' data-id=" + this.model.get('id') + ">Delete</button>" 

有这样的按钮,新的单击事件可能被解雇这样:当你实例化VehiclesView

vehicleRemove: function(e) { 
     e.preventDefault(); //Good practice for button clicks 
     var id = $(e.currentTarget).data('id'); //Id of model clicked 

     //Only one of these next two lines needs to be used 
     this.collection.remove(id); //If not persisting to server 
     this.collection.remove(id).destroy() //If persisting to server 
    }, 

而且,因为你传递它是一个名为vehicles的集合,该属性实际上应该被称为collection,而不是model。通常在单个模型视图上使用名为model的属性,或者表示哪个model表示。需要在VehiclesView内进行适当的更改,即用collection代替单词model的每个实例。

+0

谢谢你的建议! –