我目前正在开发网站水疗应用程序并尝试使用knockout.js。它位于一个 MVC 平台上,带有一个 dbdatacontroller api,使用数据和 javascript View 模型的结果。我有一个复杂的 View 模型,并且遇到了困难,主要是由于对 knockout 不熟悉。我最大的问题似乎是访问可观察值。数据库的组织方式如下:
function AdvanceSearch(data) {
var self = this;
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldTypeEnum = ko.observable(data.FieldTypeEnum);
self.AnswerType = ko.observable(data.AnswerType);
self.UserValues = ko.observableArray(ko.utils.arrayMap(data.UserValues, function (item) {
return new UserValue(item);
}));
upshot.addEntityProperties(self, "AdvanceSearch:#A.Lib.Repository");
};
function UserValue(data) {
var self = this;
self.UserProfileID = ko.observable(data.UserProfileID);
self.LoginID = ko.observable(data.LoginID);
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldValueCount = ko.observable(data.FieldValueCount);
self.FieldValueText = ko.observable(data.FieldValueText);
upshot.addEntityProperties(self, "UserValue:#A.Lib.Repository");
});
};
function AnswerType(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerTypeText = ko.observable(data.AnswerTypeText);
self.Answers = ko.observableArray(ko.utils.arrayMap(data.Answers, function (item) {
return new Answer(item);
}));
self.AnswerSliders = ko.observableArray(ko.utils.arrayMap(data.AnswerSliders, function (item) {
return new AnswerSlider(item);
}));
upshot.addEntityProperties(self, "AnswerType:#A.Lib.Repository");
}
function Answer(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerEnum = ko.observable(data.AnswerEnum);
self.AnswerText = ko.observable(data.AnswerText);
upshot.addEntityProperties(self, "Answer:#A.Lib.Repository");
}
function AnswerSlider(data) {
var self = this;
self.SliderID = ko.observable(data.SliderID);
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.SliderType = ko.observable(data.SliderType);
self.Seed = ko.observable(data.Seed);
upshot.addEntityProperties(self, "AnswerSlider:#A.Lib.Repository");
}
我的 View 模型就是这样的:
function ASViewModel() {
// Private
var self = this;
var dataSourceOptions = {
providerParameters: {
url: "/api/Dating",
operationName: "GetDatingProfile"
},
entityType: "AdvanceSearch:#A.Lib.Repository",
bufferChanges: false,
mapping: AdvanceSearch
};
// Public Properties
self.dataSource = new upshot.RemoteDataSource(dataSourceOptions)
.refresh();
self.AdvanceSearchs = self.dataSource.getEntities();
}
所以我的标记是这样的
<ol data-bind="foreach: AdvanceSearch">
<!-- ko if: FieldTypeEnum()===5 -->
<select data-bind="options: AnswerType().Answers, optionsText: 'AnswerText', optionsValue: 'AnswerEnum', optionsCaption: 'Not Specified', value: UserValues().FieldValueText"></select>
<!-- /ko -->
<!-- ko if: FieldTypeEnum()===11 -->
<input type="text" class="multilinetext" data-bind="attr: { id: 'value_'+AdvanceSearchID()}, value: UserValues().FieldValueText" />
<!-- /ko -->
所以基本上,无论我做什么,我似乎都无法访问这些项目的值。任何我访问过一个分支的地方,即。 AdvanceSearch().AnswerType().Answers
,尝试获取 $parents[1].UserValues[].FieldValueText
似乎总是未定义。就像我说的,我是 knockout 新手,所以我可能只是错过了一些东西。或者我应该使用多个 View 模型或类似的东西? (如果是这样,我该怎么做?)
谢谢。
最佳答案
根据您的评论,我想我现在知道您想要做什么。我将对其进行抽象,以便更容易理解,因为您的 ViewModel 和对象非常复杂,并且在没有解释的情况下不容易理解。
如果您有对象类型,则带有构造函数的 Book
和 Author
:
function Book(data) {
this.ISBN = ko.observable( data.ISBN );
this.Title = ko.observable( data.Title );
this.AuthorID = ko.observable( data.AuthorID );
/* other properties */
}
function Author(data) {
this.AuthorID = ko.observable( data.AuthorID );
this.Name = ko.observable( data.Name );
/* other properties */
}
要从选择
框中选择一本书并将输入
显示绑定(bind)到作者姓名,您将需要 View 模型:
var vm = {};
vm.books = ko.observableArray( /* initial data */ );
vm.authors = ko.observableArray( /* initial data */ );
vm.selectedBook = ko.observable(null);
vm.selectedBooksAuthor = ko.computed( function() {
var authors = vm.authors(),
selectedBook = vm.selectedBook();
if( !selectedBook ) return null; // cannot get .AuthorID() if selectedBook == null
var id = selectedBook.AuthorID();
for( var a in authors ) {
if( authors[a].AuthorID() == id )
return authors[a];
}
})
还有你的 HTML:
<select data-bind="options: books,
optionsText: 'Title',
optionsCaption: 'Select a book...',
value: selectedBook"></select>
<!-- ko with: selectedBooksAuthor -->
<input type="text" data-bind="value: Name" />
<!-- /ko -->
请注意,这对于大量数据来说可能会变得非常低效 - 考虑为您的计算的可观察量
使用更好的搜索算法(而不是这里使用的“线性”),即选定的BooksAuthor
编辑:
请参阅this fiddle进行工作演示。
关于javascript - 如何访问同一 viewModel 中不同分支的后代?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12659544/