【问题标题】:Remove corresponding item when delete button is clicked. BackboneJs单击删除按钮时删除相应的项目。骨干网
【发布时间】:2016-02-13 15:06:39
【问题描述】:

我目前正在学习 BackboneJs 并试图了解 Backbone 如何处理事件。我有一个简单的项目列表,每个项目旁边都有一个delete 按钮。我试图弄清楚为什么在控制台中注册了单击事件(删除按钮)但未删除该项目。这是我所拥有的:

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();

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

【问题讨论】:

    标签: javascript jquery backbone.js


    【解决方案1】:

    既然你有一个项目视图,最好给它一个删除自己的功能。这样您就不必破解从 DOM 中读取内容的方式来根据单击的项目视图元素查找相关模型。

    另外,你应该使用 Backbone.View 的 remove() 方法而不是 jQuery remove() 方法,因为它可以安全地删除视图上注册的主干事件,以及调用 jQuery remove() 来删除元素来自 DOM。

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

    不需要自己手动初始化集合中的模型,主干会自动完成,这就是集合model属性的用途。

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

    此外,正如 dskoda1 已经提到的,您不应该使用 model 选项传递 Backbone.Collection,模型和集合是 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>

    【讨论】:

    • 非常感谢您的解释!
    【解决方案2】:

    您可能希望在按钮上使用的有用属性是data-id。将此值设置为模型 ID 将允许您更清晰地选择要删除的正确模型。新按钮 html 现在是:

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

    拥有这样的按钮,新的点击事件可以这样触发:

        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
        },
    

    另外,当您实例化您的 VehiclesView 时,由于您向其传递了一个名为 vehicles 的集合,因此该属性实际上应该称为 collection,而不是 model。一个名为model 的属性通常用于单个模型视图,或者表示modelcollection 所代表的。需要在VehiclesView 内部进行适当的更改,即将单词model 的每个实例替换为collection

    【讨论】:

    • 感谢您的建议!
    【解决方案3】:

    this.remove()?

    此时,Backbone 已经知道您要删除哪个模型,因此无需指定 jQuery 选择器。

    当然,.remove() 只会从 DOM 中删除元素。您是否正在寻找 model.destroy() 来向服务器发送 DELETE 命令?

    【讨论】:

    • this.remove() 有效,但现在它会在单击任何一个按钮时删除所有三个项目。当单击相应的删除按钮而不是所有项目时,是否可以删除项目?现在我只在研究如何从 DOM 中删除元素,而不是从服务器中删除,但感谢您提供的信息!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2013-10-09
    • 2016-05-07
    • 1970-01-01
    • 2023-01-05
    相关资源
    最近更新 更多