多次触发 Backbonejs 事件

Backbonejs events fired multiple times

我开发了一个 table 自定义 headers/ts 和 content/td。当我定义一个事件并单击钩子按钮时,该事件多次触发:

观看次数

//VISTA DE CABECERA
var FieldTableHeaders = Backbone.View.extend( {
    el: $("#entity-fields tr"),
    template: _.template("<th><%= field.Placeholder %></th>"),
    initialize: function(){
        this.render();
    },
    render: function() {
        console.log(this.model);
        $(this.el).append(this.template({
            field: this.model
        }));

        return $(this.el);
    },
});

//VISTA DE CONTENIDO
var FieldTableContent = Backbone.View.extend( {
    el: $("#entity-items"),
    template: _.template($("#fieldActions").html()),
    events: {
        'click .entityView': 'example'
    },
    initialize: function(options){
        this.render();
    },
    render: function() {
        $(this.el).append(this.template({
            field: this.model
        }));

        return $(this.el);
    },
    example: function(){
        alert('sadasdasd')
    }
});

车型

// MODELO DE ENTIDAD UNICA
var CoreEntityModel = Backbone.Model.extend({
    defaults: {
        _EntityId: null,
        _EntityStatus: 0,
        _EntityCreateDate: '0000-00-00 00:00:00',
        _EntityCreateUser: 0,
        _EntityUpdateDate: '0000-00-00 00:00:00',
        _EntityUpdateUser: 0
    },
    idAttribute: "_EntityId"
});

//COLECCIÓN DE ENTIDADES
var EntityCollection = Backbone.Collection.extend({
    model: CoreEntityModel
});

//MODELO DE APLICACION
var CoreAplicacionModel = Backbone.Model.extend({
    //Instanciar app
    defaults: {
        ElementsPerPage: 20,
        Fields: {},
        ID: null,
        Name: '',
        NameSingular: '',
        Permalink: '',
        Items: {
            Results: [],
            Count: 0,
            Page: 0
        }
    },
    //Cargar configuracion de app
    initialize: function (attrs, opts) {
        var self = this;
        self.Permalink = attrs;

        //Listamos aplicacion
        $.ajax(API_PATH + '/apps', {
            type: "GET",
            dataType: "json",
            data: {
                permalink: self.Permalink
            },
            success: function (response) {
                var data = response[0];

                self.set({
                    ElementsPerPage: data.ElementsPerPage,
                    Fields: data.Fields,
                    ID: data.ID,
                    Name: data.Name,
                    NameSingular: data.NameSingular,
                    Permalink: data.Permalink
                });

                var Model = self.get('Fields');
                var Fields = []

                //Recogemos solo campos visibles para cabecera
                for (var fieldName in self.get('Fields')) {
                    if (Model[fieldName].Visible) {
                        new FieldTableHeaders({
                            model: Model[fieldName]
                        });

                        Fields.push(fieldName);
                    }
                };

                self.list(self.get('Items').Page, function(result, data){
                    if(result){
                        new FieldTableHeaders({
                            model: {Placeholder: 'Acciones'}
                        });

                        //Recogemos solo campos visibles para contenido
                        var Items = self.get('Items');
                        for (var i in Items.Results){
                            var Values = [];

                            for (var u in Fields) {
                                Values.push(Items.Results[i][Fields[u]]);
                            }

                            new FieldTableContent({model: Values});
                        }
                    }else{
                        //Ningun registro
                    }
                });
            },
            error: function (response) {
                window.location.href = "pagina-no-encontrada";
            }
        });
    },
    // Listar elementos de app
    list: function(page, callback){
        var self = this;

        $.ajax(API_PATH + '/app/'+self.Permalink, {
            type: "GET",
            dataType: "json",
            data: {
                page: page
            },
            success: function (response) {
                var Items = self.get('Items');
                Items.Page++;
                Items.Count = response.count;
                for (var item in response.data) {
                    Items.Results.push(response.data[item]);
                }

                self.set({Items: Items});

                //COLECCIÓN DE ENTIDADES
                var entity_collection = new EntityCollection();
                entity_collection.add(self.get("Items"));

                if (typeof(callback) == "function") {
                    callback(true, response);
                }
            },
            error: function (response) {
                //NO HAY DATOS O ACCESO A API
                if (typeof(callback) == "function") {
                    callback(false, null);
                }
            }
        });
    },
    idAttribute: "ID"
});

事件在 table 中每行触发一次。

这是内容模板:

<script type="text/html" id="fieldActions">
    <tr>
        <% _.each(field, function(val, i) { %> <td><%= val %></td> <% }); %>
        <td class="text-center">
            <a class="btn btn-info btn-rounded btn-xs entityView"><i class="fa fa-eye"></i> Ver</a>
            <a class="btn btn-warning btn-rounded btn-xs entityEdit"><i class="fa fa-pencil"></i> Editar</a>
            <a class="btn btn-danger btn-rounded btn-xs entityDelete"><i class="fa fa-trash"></i> Eliminar</a>
        </td>
    </tr>
</script>

有什么问题?

嗯,首先你应该知道 $ (this.el) 不是必需的,因为 backbone 会自动完成它,它会变成 this.$el

回答您的问题,根据 code,每个视图将其事件委托给包装在她内部的每个元素。
因此它将 'click .entityView':'example' 委托给 el: $("#entity-items").
中的每个 .entityView 也就是说,第一个 .entityView 将分配与 table 中的元素一样多的事件。而最后.entityView只有1个事件。

覆盖 delegate 方法的解决方案可能有效:

// ...extend({
delegate: function(eventName, selector, listener) {
    this.$el.find(selector).last().on(eventName + '.delegateEvents' + this.cid, listener);
    return this;
},
// ...