【问题标题】:Backbonejs events fired multiple timesBackbonejs 事件多次触发
【发布时间】:2017-06-29 18:09:35
【问题描述】:

我正在开发一个带有自定义标题/ts 和内容/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"
});

该事件在表中的每一行触发一次。

这是内容模板:

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

有什么问题?

【问题讨论】:

  • 能不能把调用EntityFields的代码也暴露一下?另外一个建议是使用class 而不是id 用于entityViewentityDeleteentityEdit,因为您可以有多个字段并且id 属性应该在页面上是唯一的
  • 你是对的。固定和添加模型。我是骨干新手。
  • 我正在尝试使用 jquery 事件 $(".entityView").click(function(){self.example();}) 但没有用

标签: javascript jquery events backbone.js


【解决方案1】:

嗯,你应该知道的第一件事是$ (this.el) 不是必需的,因为主干会自动执行它,它就像this.$el

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

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

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

【讨论】:

  • 添加并修复。 Muchas gracias, me estaba volviendo loco :)
  • SO 是英文网站,请避免在内容中使用任何其他语言。西班牙语内容见Stack Overflow en español
  • 另外,不要覆盖delegate来实现这一点,而是解决设计中的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多