我在这里有一个测试用例:http://tremby.net/knockouttest/page1.php
我正在使用pjax进行页面转换。单击上面测试用例的第1页和第2页之间的异步加载两个页面,然后替换#main
元素的内容。在此过程中会推送浏览器历史记录状态,因此位置栏中的URL会更新,后退按钮会让我们回到原来的位置。
第1页上的列表中填充了knockout的foreach
绑定和我定义的List
模型(在头部的内联脚本中)。在第1页的ready
上,内联脚本运行ko.applyBindings
,因此填充了列表。
“添加项目”按钮将一个项目添加到视图模型中,然后将该项目添加到列表中。
添加一些项目,然后转到第2页,然后返回到第1页,列表是新鲜的,其最初的3个项目,添加项目按钮仍然有效。这对我们的用例很好。
添加一些项目,然后转到第2页,但是另一方面,使用浏览器的后退按钮返回到第1页,是我的问题所在。新项目仍然可见(这是好的,并且
当使用浏览器的后退按钮时,对我们的用例至关重要),但“添加项目”按钮现在已被破坏。将新项目推送到observableArray
的代码肯定在运行,但似乎绑定已经消失,因此淘汰赛不知道添加新的DOM元素。
我无法在ko.applyBindings
上再次运行popstate
功能,或者淘汰赛现在认为我希望每个现有项目都可以为列表中的每个项目复制,之后每次点击“添加项目”都会给出多个新项目。
我有一种强烈的感觉,有一些显而易见的东西我不见了,但我找不到任何看起来像文件中有帮助的东西。任何帮助将不胜感激。
答案 0 :(得分:1)
您看到了这个现象,因为尽管已经绑定的视图模型的UI,你有没有坚持它的任何地方浏览器历史可以以重建页面中,你所期望的状态访问它。使用浏览器的内置back
和forward
按钮也可以观察到此行为。我选择用来解决这个问题的常用模式如下:
首先,将this
分配给变量,这将为您节省hassle later on。视图模型现在应该看起来像这样;
function List(items) {
var self = this;
self.items = ko.observableArray(items)
self.addItem = function(text) {
self.items.push(text)
}
}
现在创建一个计算的observable,用于序列化视图模型的当前状态。完全取决于您如何选择实施它。
self.toJson = ko.computed(function(){
/*** Serialise self.items() and return the string ***/
return myJsonString;
});
接下来,将计算机绑定到隐藏输入,这将确保视图模型保留在表单数据中,以便稍后再对视图模型进行补充。
<input id="serialisedItems" type="hidden" data-bind="value: toJson" value="[1,4,3]" />
最后,以这种方式在$.ready()
上重新水化视图模型;
$(function() {
var items = $('#serialisedItems').val();
/*** Deserialise items before passing into the List ***/
var list = new List(deserialisedItems);
ko.applyBindings(list);
});
此时我还应该指出,列表已经通过设置<input>
的value属性进行了初始化。