我正在编写一个 Knockout.js 应用程序,它在实体图上执行基本的 CRUD 操作。我从我的服务器加载了两个 JSON 编码的对象:第一个是包含一堆产品详细信息的数组,第二个是索引图像列表,如下所示:
function UploadedImage(data) {
this.UploadedImageId = data.UploadedImageId;
this.Url = data.Url;
this.Name = data.Name;
this.AltText = data.AltText;
}
...通过 AJAX 请求存储在 ViewModel 中,如下所示:
$.post("@Url.Action("JsonRepairData")", {}, function (response) {
self.repairData(_.map(response.repairData, function(d) { return new AppleProduct(d); }));
self.images(_.map(response.images, function (i) { return new UploadedImage(i); }));
self.dataLoaded(true);
}, 'json');
我已经验证数据在对象图中和图像数组中都正确加载。对象图中的图像 ID 对应于数组中的图像 ID。为了显示为对象图中的相关数据条目选择的图像,我选择了一个选择列表,如下所示:
<tbody data-bind="foreach: repairData">
<tr>
<td>@Html.TextBoxFor(m => m.Name, new { data_bind = "value: Name" })</td>
<td><select data-bind="options: $root.images, optionsCaption: 'Pick an image...', optionsValue: 'UploadedImageId', optionsText: 'Name', value: UploadedImageId"></select></td>
<td data-bind="html: ImgTag"></td>
<td><a href="#" data-bind="click: $root.deleteProduct">delete</a></td>
</tr>
</tbody>
请注意,包含在 ViewModel 中的 repairData 是上述对象图。所有其他数据都正确绑定。选择框已成功填充。在操作选择框时,ViewModel 中绑定的 UploadedImageId 的值会更新。但是,ViewModel 的 UploadedImageId 初始值(来自对象图)被忽略,当页面呈现时,UploadImageId 立即更新为未定义。这是在对象图中设置 UploadedImageId 的初始值的方式:
function AppleProduct(data) {
var productSelf = this;
this.Id = data.Id;
this.Name = ko.observable(data.Name);
this.UploadedImageId = ko.observable(data.UploadedImageId);
this.Variations = ko.observableArray(_.map(data.Variations, function (v) { return new ProductSeries(v); }));
this.ImgTag = ko.computed(function () {
var img = _.find(self.images(), function (i) { return i.UploadedImageId == productSelf.UploadedImageId(); });
return img ? '<img src="'+img.Url+'" />' : '';
});
// Remove computed ImgTag from data addressed to the server
this.toJSON = function () {
var copy = ko.toJS(this);
delete copy.ImgTag;
return copy;
};
}
我一直试图弄清楚如何让选择框正确设置几个小时,但我仍然完全被难住了。我所能确定的是,在 2.1.0 淘汰赛 js 源文件中,负责在第 1402 行(见下文)设置选择框初始值的代码被传递了两次。第一次模型值正确对应于图像 ID,但 element.options.length == 0 并且不使用模型值。第二次传递此代码时,模型值都未定义,但选择框已填充(因此 element.options.length 是正数),因此再次未设置正确的初始值。
for (var i = element.options.length - 1; i >= 0; i--) {
if (ko.selectExtensions.readValue(element.options[i]) == value) {
element.selectedIndex = i;
break;
}
}
任何有助于理解我所缺少的东西将不胜感激!