gpt4 book ai didi

javascript - 主干 View 不应在不同实例中具有相同的数据,但确实如此

转载 作者:行者123 更新时间:2023-11-28 20:20:58 24 4
gpt4 key购买 nike

我有一个主干 View ,其渲染函数中包含以下代码(请注意 3 console.log(that.ticketSelector.attributes);):

    if(typeof this.ticketSelector === 'undefined') {
// TODO: first fetch tickets
this.ticketSelector = new DataTable({
collection: that.model.tickets,

icon: "ticket",
title: "Tickets",
customClasses: ["ticket", "subject-selector"],

columns: [
{text: 'Name', modelKey: "name", col: 1},
{text: 'Date', modelKey: "date", col: 2},
{text: 'Owner', modelKey: "owner", col: 3},
{text: 'Description', modelKey: "description", col: 4}
]
});
this.$('.subject-selectors').append(this.ticketSelector.$el);
this.ticketSelector.render().resize();
} else {
this.ticketSelector.render().resize();
}

console.log(that.ticketSelector.attributes);

if(typeof this.alarmSelector === 'undefined') {
// TODO: first fetch tickets
this.alarmSelector = new DataTable({
collection: that.model.alarms,

icon: "warning-sign",
title: "Alarms",
customClasses: ["alarm", "subject-selector"],

columns: [
{text: 'Name', modelKey: "name", col: 1},
{text: 'Date', modelKey: "date", col: 2},
{text: 'Owner', modelKey: "owner", col: 3},
{text: 'Description', modelKey: "description", col: 4}
]
});
this.$('.subject-selectors').append(this.alarmSelector.$el);
this.alarmSelector.render().resize();
} else {
this.alarmSelector.render().resize();
}

console.log(that.ticketSelector.attributes);

if(typeof this.taskSelector === 'undefined') {
// TODO: first fetch tickets
this.taskSelector = new DataTable({
collection: that.model.tasks,

icon: "tasks",
title: "Tasks",
customClasses: ["task", "subject-selector"],

columns: [
{text: 'Name', modelKey: "name", col: 1},
{text: 'Date', modelKey: "date", col: 2},
{text: 'Owner', modelKey: "owner", col: 3},
{text: 'Description', modelKey: "description", col: 4}
]
});
this.$('.subject-selectors').append(this.taskSelector.$el);
this.taskSelector.render().resize();
} else {
this.taskSelector.render().resize();
}

console.log(that.ticketSelector.attributes);

在控制台中我看到:

Object {icon: "ticket", title: "Tickets", columns: Array[4], classes: Array[2]}
Object {icon: "warning-sign", title: "Alarms", columns: Array[4], classes: Array[2]}
Object {icon: "tasks", title: "Tasks", columns: Array[4], classes: Array[2]}

我期望的地方:

Object {icon: "ticket", title: "Tickets", columns: Array[4], classes: Array[2]}
Object {icon: "ticket", title: "Tickets", columns: Array[4], classes: Array[2]}
Object {icon: "ticket", title: "Tickets", columns: Array[4], classes: Array[2]}

这是我的数据 TableView :

var DataTable = Backbone.View.extend({

tag: 'div',
className: 'data-table',

initialize: function(opts) {
if(typeof opts.parent !== 'undefined') {
this.parent = opts.parent;
}
if(typeof opts.icon !== 'undefined') {
this.attributes.icon = opts.icon;
}
if(typeof opts.title !== 'undefined') {
this.attributes.title = opts.title;
}
if(typeof opts.columns !== 'undefined') {
this.attributes.columns = opts.columns;
}
if(typeof opts.customClasses !== 'undefined') {
this.attributes.classes = opts.customClasses;
}
},

attributes: {},

template: function() {
var temp;

$.ajax(root + 'templates/data-table.html', {
success: function(data) {
// console.log(data);
temp = Mustache.compile($(data).filter('#data-table-template').html());
},

async: false
});

return temp;
}(),

events: {
},

serialize: function() {
var that = this;
return {
root: root,
icon: that.attributes.icon,
title: that.attributes.title,
columns: that.attributes.columns
};
},

resize: function() {
var that = this;
},

subView: [],

render: function() {
var that = this;

var html = this.template(this.serialize());

this.$el.html(html);

if(that.attributes.classes) {
_.each(that.attributes.classes, function(c) {
that.$el.addClass(c);
});
}

this.collection.each(function(row) {
tempView = new DataTableRow({ model: row, parent: that, columns: that.attributes.columns });
that.subView.push(tempView);
that.$('.tbody').append(tempView.$el);
tempView.render();
});

this.$('.tbody').mCustomScrollbar({
scrollInertia: 0,
});

return this;
}

});

var DataTableRow = Backbone.View.extend({

tag: 'div',
className: 'tr',

initialize: function(opts) {
var that = this;

if(typeof opts.parent !== 'undefined') {
this.parent = opts.parent;
}

if(typeof opts.columns !== 'undefined') {
var temp = {};
that.attributes.columns = _.map(opts.columns, function(col) {
return {
text: that.model.get(col.modelKey),
col: col.col
};
});
}
},

attributes: { columns: [] },

template: function() {
var temp;

$.ajax(root + 'templates/data-table.html', {
success: function(data) {
// console.log(data);
temp = Mustache.compile($(data).filter('#data-table-row-template').html());
},

async: false
});

return temp;
}(),

events: {
},

serialize: function() {
var that = this;
return {
root: root,
columns: that.attributes.columns
};
},

resize: function() {
var that = this;
},

render: function() {
var that = this;

var html = this.template(this.serialize());

this.$el.html(html);

return this;
}

});

我知道我可以通过为每个数据表创建不同的 View 来解决这个问题,但这应该可行,但我不知道为什么它不行。这里有什么帮助吗?谢谢。

编辑:为了更好地理解这一点,这里是下划线扩展函数:

_.extend = function(obj) {
each(slice.call(arguments, 1), function(source) {
if (source) {
for (var prop in source) {
obj[prop] = source[prop];
}
}
});
return obj;
};

是什么让这些属性附加到原型(prototype)上?

最佳答案

您的属性 {}位于原型(prototype)上,因此它将在对象的所有实例之间共享。您需要为每个实例拥有一个attributes 对象。

而不是这样的:

var DataTable = Backbone.View.extend({
attributes: {}
});

您需要在每次初始化时创建一个新对象:

var DataTable = Backbone.View.extend({
attributes: {},
initialize: function(options){
this.attributes = {};
}
});

正如 @muistooshort 指出的,您的 subViews 数组和 DataTableRow.prototype.attributes 也存在这个问题。传递给 extend 的对象中的任何键值对都放置在该对象的原型(prototype)上,这意味着该对象的新实例将全部共享这些属性。这就是您的所有函数在每个实例上的最终结果,但这也意味着其他所有函数也是如此,因此您需要确保每个实例的事物都正确初始化。

编辑

Backbone.View.extend_.extend 无关,只是它碰巧使用它有一个助手,就像任何其他代码一样。

  • _.extend 获取多个对象并将其属性复制到第一个对象上。
  • Backbone.View.extend 接受单个对象,并返回一个新的构造函数,该函数将构造一个以该对象为其原型(prototype)的对象,并且还继承第一个构造函数的原型(prototype)extend 被调用。

https://github.com/jashkenas/backbone/blob/master/backbone.js#L1532

假设你有一个像这样的对象:

Backbone.View 构造函数在调用时将创建一个以 Backbone.View.prototype 作为其原型(prototype)并具有标准 View 方法的新对象。

当您执行 var DataTable = Backbone.View.extend(newproto_obj) 时,您现在拥有以下内容:

DataTable 构造函数,调用时将创建一个新对象,该对象的原型(prototype)具有来自 newproto_objBackbone.View.prototype 的值作为该原型(prototype)的原型(prototype)。

这称为原型(prototype)链,这就是 JavaScript 进行继承的方式。当您创建一个新对象时,它没有自己的属性,除非它们是由 Backbone 在构造函数或 initialize 函数中设置的。如果您尝试访问对象上的属性但该属性不存在,它将查看其原型(prototype)是否具有该名称的属性。因为原型(prototype)对象是跨实例共享的单个公共(public)对象,所以修改它将会改变每个实例。

关于javascript - 主干 View 不应在不同实例中具有相同的数据,但确实如此,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18327355/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com