多次触发 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;
},
// ...
我开发了一个 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;
},
// ...