我遇到了对订阅更新没有约束力的淘汰模型的问题。我有一个C#MVC页面,它向模板提供一个模型,该模型被解析为Json并作为ko.applyBindings
的ViewModel赋值的一部分进行原始传递。我订阅了一个observable,它调用一个方法来执行viewModel数据的更新。不相关的东西被撤出并重命名为例如:
var myViewModel = function (data) {
var self = this;
self.CurrentPage = ko.observable();
self.SomeComplexArray= ko.observableArray([]);
self.Pager().CurrentPage.subscribe(function (newPage) {
self.UpdateMyViewModel(newPage);
});
self.UpdateMyViewModel= function (newPage) {
var postData = { PageNumber: newPage };
$.post('/Article/GetMyModelSearchByPage', postData, function (data) {
ko.mapping.fromJS(data, {}, self);;
});
};
当我执行日志记录时,我可以看到所有数据,而且看起来都是正确的。使用相同的方法来生成初始模型和更新的模型。我在其他页面上使用过这种技术,每次都能完美运行。但是,在这种情况下,我正在寻找它来绑定/更新SomeComplexArray
,而这只是没有发生。如果我尝试手动执行此操作,则无法在阵列上获得正确的绑定。我想知道是否有一些显而易见的事情表明我做错了以至于我只是不知所措。
编辑:我不知道ko.mapping可以被指向罪魁祸首。标准模型更改也不会影响界面。这是一种在限制意义上不起作用的东西。我有一个p元素,可见绑定到数组的长度和一个div元素,点击绑定到一个从SomeComplexArray弹出项目的函数。我可以在控制台日志中看到它正在执行其功能(后续点击导致未定义'没有该功能)。但是,p元素永远不会显示。初始数组只有2个项目,因此只需单击即可清空它:
<p data-bind="visible: SomeComplexArray().length === 0">nothing found</p>
<div data-bind="click: function() { UpdateArray(); }">try it manually</div>
-- in js model
self.UpdateArray = function () {
console.log(self.SomeComplexArray());
console.log(self.SomeComplexArray().pop());
console.log(self.SomeComplexArray());
console.log(self.SomeComplexArray().pop());
console.log(self.SomeComplexArray());
});
来自评论@Matt Burland的编辑2:,我已经修改了如何调用pop,手动方法现在可以动态修改元素。但是,ko.mapping仍然无法正常运行。在测试中,我在调用ko.mapping之后执行了特定行的console.log。没有对observableArray进行任何更改。
答案 0 :(得分:0)
我在JSFiddle创建了一个关于淘汰情况的测试。
你必须在没有paranthesis的情况下调用你的数组函数。我测试了这部分:
self.UpdateArray = function () {
self.SomeComplexArray.pop();
};
似乎正在JSFiddle方面工作。
答案 1 :(得分:0)
我不确定为什么,但似乎ko.mapping很难重新映射视图模型。由于没有一个字段被映射到self
我的假设是在某个地方发生了一个异常,即ko.mapping只是吞咽或者由于其他原因没有报告。鉴于我可以使用来自@MattBurland的有用提示手动操作数组,我决定回溯一下并仅更新需要直接更改数据负载的元素。我最终为我的viewModel创建了一个Init
函数,并使用ko.mapping直接在那里填充项目:
self.Init = function (jsonData) {
self.CurrentPage(0);
self.Items(ko.mapping.fromJS(jsonData.Items)());
self.TotalItems(jsonData.TotalItems);
// More stuff below here not relevant to question
}
这里的主要区别是ko.mapping.fromJS结果需要在observableArray识别它之前作为函数调用。鉴于这是有效的,我的控制器将在AJAX请求期间提供相同的对象,它几乎是复制/过去:
self.UpdateMyViewModel= function (newPage) {
var postData = { PageNumber: newPage };
$.post('/Article/GetMyModelSearchByPage', postData, function (data) {
self.Items(ko.mapping.fromJS(JSON.parse(data).Items)());
});
};
对于大多数情况,这可能并不理想,但由于在更新期间没有对viewModel进行大量操作,因此这提供了一种可行的解决方案。我仍然想知道为什么ko.mapping不会重新映射顶层的viewModel,但回想起来它可能本来就是一场灾难,因为它已经被修改了#34; viewModel中服务器必须替换的数据。这个解决方案简单快捷。