我正在将功能构建到用户可以多次执行的网页上 . 通过用户的操作,使用ko.applyBindings()创建对象/模型并将其应用于HTML .
数据绑定HTML是通过jQuery模板创建的 .
到现在为止还挺好 .
当我通过创建第二个对象/模型并调用ko.applyBindings()重复此步骤时,我遇到两个问题:
-
标记显示上一个对象/模型以及新对象/模型 .
-
与对象/模型中的某个属性相关的javascript错误,尽管它仍然在标记中呈现 .
为了解决这个问题,在第一次传递之后,我调用jQuery的.empty()来删除包含所有数据绑定属性的模板化HTML,这样它就不再存在于DOM中了 . 当用户启动第二次传递的过程时,数据绑定的HTML将重新添加到DOM .
但就像我说的那样,当HTML重新添加到DOM并重新绑定到新的对象/模型时,它仍然包含来自第一个对象/模型的数据,我仍然得到不会发生的JS错误在第一次通过期间 .
结论似乎是Knockout坚持这些绑定属性,即使从DOM中删除了标记 .
所以我正在寻找的是从Knockout中删除这些绑定属性的方法;告诉淘汰赛,不再有可观察的模型 . 有没有办法做到这一点?
EDIT
基本过程是用户上传文件;然后服务器使用JSON对象进行响应,将数据绑定的HTML添加到DOM中,然后将JSON对象模型绑定到此HTML
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
一旦用户在模型上做了一些选择,就会将相同的对象发回服务器,从DOM中删除数据绑定的HTML,然后我有以下JS
mn.AccountCreationModel = null;
当用户希望再次这样做时,重复所有这些步骤 .
我担心代码太“参与”了jsFiddle演示 .
9 回答
您是否尝试在DOM元素上调用knockout的clean节点方法来处理内存绑定对象?
然后使用新视图模型再次对该元素应用knockout绑定将更新视图绑定 .
对于我正在研究的项目,我写了一个简单的
ko.unapplyBindings
函数,它接受一个jQuery节点和remove boolean . 它首先取消绑定所有jQuery事件,因为ko.cleanNode
方法没有测试内存泄漏,它似乎工作得很好 .你可以尝试使用knockout提供的with binding:http://knockoutjs.com/documentation/with-binding.html想法是使用apply bindings一次,每当你的数据发生变化时,只需更新你的模型 .
假设您有一个顶级视图模型storeViewModel,您的购物车由cartViewModel表示,以及该购物车中的项目列表 - 例如cartItemsViewModel .
您可以将顶级模型 - storeViewModel绑定到整个页面 . 然后,您可以分离页面中负责购物车或购物车商品的部分 .
让我们假设cartItemsViewModel具有以下结构:
cartItemsViewModel在开头可以为空 .
步骤看起来像这样:
var storeViewModel = ko.mapping.fromJS(modelFromServer)
ko.applyBindings(storeViewModel);
storeViewModel.cartItemsViewModel(actualCartItemsModel);
如果您想清除购物车项目:
storeViewModel.cartItemsViewModel(null);
Knockout将处理html - 即当模型不为空时它将出现,div的内容(带有“with binding”的那个)将消失 .
我必须在每次单击搜索按钮时调用ko.applyBinding,并且从服务器返回已过滤的数据,在这种情况下,在不使用ko.cleanNode的情况下为我工作 .
我经历过,如果我们用模板替换foreach,那么它应该在collections / observableArray的情况下正常工作 .
您可能会发现此方案很有用 .
而不是使用KO 's internal functions and dealing with JQuery'的毯子事件处理程序删除,更好的主意是使用
with
或template
绑定 . 当你这样做时,ko重新创建DOM的那一部分,因此它会自动清理 . 这也是推荐的方式,见这里:https://stackoverflow.com/a/15069509/207661 .我认为最好在整个时间内保持绑定,并简单地更新与之关联的数据 . 我遇到了这个问题,发现只是在我保存数据的数组上使用
.resetAll()
方法调用是最有效的方法 .基本上你可以从一些包含要通过ViewModel呈现的数据的全局var开始:
我花了一段时间才意识到我不能让
myLiveData
成为一个正常的数组 -ko.oberservableArray
部分很重要 .然后你可以继续做你想做的任何事情
myLiveData
. 例如,拨打$.getJSON
电话:完成此操作后,您可以像往常一样使用ViewModel继续应用绑定:
然后在HTML中,像往常一样使用
myData
.这样,您可以从任何函数中使用myLiveData进行清理 . 例如,如果要每隔几秒更新一次,只需将
$.getJSON
行包装在函数中并在其上调用setInterval
即可 . 只要记得保留myLiveData.removeAll();
行,就永远不需要删除绑定 .除非您的数据非常庞大,否则用户甚至无法注意重置阵列然后再添加最新数据的时间 .
我最近遇到了内存泄漏问题,
ko.cleanNode(element);
不会对我这么做 -ko.removeNode(element);
. Javascript + Knockout.js memory leak - How to make sure object is being destroyed?你有没有想过这个:
我想出了这个,因为在Knockout中,我发现了这段代码
所以对我来说,这不是一个已经绑定的问题,它的错误没有被 grab 和处理......
我发现如果视图模型包含许多div绑定,清除
ko.applyBindings(new someModelView);
的最佳方法是使用:ko.cleanNode($("body")[0]);
这允许您动态调用新的ko.applyBindings(new someModelView2);
,而不必担心以前的视图模型仍然被绑定 .