【发布时间】:2014-01-31 02:48:44
【问题描述】:
我正在使用 Knockout 3 构建呈现为表格的可编辑网格。网格由 Row 对象组成,每行一个。 Row 内部是一个 Cells 数组(每列一个),然后每个 Cell 内部是一个或多个 Slot 对象。插槽在表格单元格中呈现为列表。
外层 Row 定义了一个 RowIndex observable,其中的 Cells 有一个计算出的 observable,它读取行的 RowIndex,而 Slots 有一个计算出的 observable,它从 Cell 中读取 RowIndex。
问题是当我在Row上设置一个新的RowIndex时,它会传播到Cell,但是当Cell包含Slots时,KO抛出异常:“Uncaught TypeError: Property 'callback' of object [object Object] is not a function”在 knockout-3.0.0.debug.js 的第 1021 行。从 Chrome 开发者工具中,我看到订阅的 callback 属性确实是未定义的。
如果 Cell 不包含任何槽,则在 Row 上设置 RowIndex 会导致它毫无问题地传播到 Cell。
var Row = function(data) {
var self = this;
this.Cells = [];
this.RowIndex = ko.observable(data.rowIndex);
// omitted code...
}
var Cell = function(data, row) {
var self = this;
this.row = row;
this.Enabled = ko.observable(true);
// When row is disabled, disable the cell
row.Enabled.subscribe(function (value) {
if (value == false) {
self.Enabled(false);
}
});
// RowIndex comes from parent row
this.RowIndex = ko.computed(function () {
return self.row.RowIndex();
}, this);
// omitted code ...
}
var Slot = function(data, cell, enabled) {
var self = this;
this.cell = cell;
// RowIndex is cells's RowIndex
this.RowIndex = ko.computed(function() {
return self.cell.RowIndex();
}, this);
// Any change marks slot as dirty
self.Title.subscribe(this.updated);
self.SeatCount.subscribe(this.updated);
self.RowIndex.subscribe(this.updated);
this.updated = function() {
if (self.Action() == actions.None)
{
self.Action(actions.Update);
}
}
// When cell is disabled, I feel disabled, too.
cell.Enabled.subscribe(function(value) {
if (value == false) {
self.Enabled(false);
}
});
// omitted code
}
var ViewModel(colHeadings, rowHeadings, slots) {
var self = this;
// Code omitted to iterate the slots and build the rows
// and cells
// Invoked on a click to add a row at index
this.addRow = function(index) {
var row = new Row({ heading: "New Row", rowIndex: index });
for (var ci=0; ci<this.columnCount; ci++) {
var c = new Cell({ colIndex: ci }, row);
row.Cells.push(c);
}
self.RowData.splice(index, 0, row);
self.renumberRows();
};
// Invoked on a click to remove (disable) a row
this.removeRow = function(row) {
row.Enabled(false);
self.renumberRows();
};
// Sequentially number the enabled rows
this.renumberRows = function() {
var index = 0;
for (var ri=0; ri<self.RowData().length; ri++) {
var row = self.RowData()[ri];
if (row.Enabled()) {
row.RowIndex(index);
index++;
}
}
};
}
当我通过 addRow 在 ViewModel 上插入新行时,会分配 RowIndex,并将其传播到单元格。那太好了。但是新的 Row's Cells 还没有包含任何 Slots,所以到目前为止没有错误。但随后我必须重新编号行,以便 RowIndex 是连续的。一旦我在具有插槽的单元格的行上设置行索引,我就会得到异常。 removeRow 也是如此。
【问题讨论】:
-
如果
callback未定义,这意味着subscribe在您的代码中的某处被调用,而没有提供任何“回调”。 -
嗯。我在几个地方使用订阅,但我每次都提供一个回调函数。我将编辑代码以包含它们。
-
谢谢。这正是我需要给你答案的。