如何清除/删除Knockout.js观察到的绑定?如何清除/删除Knockout.js观察到的绑定?

2019-05-13 11:18发布

我建立的功能上,用户可以进行多次的网页。 通过用户的动作,对象/模型被创建,并使用ko.applyBindings施加到HTML()。

数据绑定HTML通过jQuery的模板创建的。

到现在为止还挺好。

当我重复此步骤通过创建一个第二对象/模型和呼叫ko.applyBindings()我遇到两个问题:

  1. 该标记显示了一个对象/模型以及新的对象/模型。
  2. 发生了JavaScript错误与在对象/模型的属性之一,尽管它在标记仍然呈现。

为了解决这个问题,第一遍后,我打电话jQuery的.empty(),以去除其中包含的所有数据绑定属性,所以它在DOM不再是模板HTML。 当用户开始该过程用于第二遍的数据绑定HTML被重新添加到DOM。

但是就像我说的,HTML是当重新加入到DOM并重新绑定到新的对象/模型,它仍包括从第一对象/模型数据,和我仍然得到不出现JS错误在第一遍期间。

结论似乎是,淘汰赛是持有这些绑定属性,即使标记从DOM中删除。

所以,我正在寻找的是去除这些淘汰赛绑定属性的手段; 告诉淘汰赛,有不再是一个可观察的模型。 有没有办法做到这一点?

编辑

基本过程是,用户上传的文件; 服务器然后用JSON对象响应,则数据绑定HTML被添加到DOM,则JSON对象模型是使用绑定到此HTML

mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);

一旦用户对模型做了一些选择,同一个对象回发到服务器,数据绑定HTML从DOM然后取出,然后我有以下JS

mn.AccountCreationModel = null;

当用户希望这样做一次,重复所有这些步骤。

恐怕代码太“参与”做的jsfiddle演示。

Answer 1:

你有没有打过电话的DOM元素淘汰赛的清洁节点的方法在内存中绑定对象处置的?

var element = $('#elementId')[0]; 
ko.cleanNode(element);

然后用新的视图模型重新申请只是元素的淘汰赛绑定将更新您的视图结合。



Answer 2:

对于一个项目,我的工作,我写了一个简单ko.unapplyBindings接受一个jQuery节点和删除布尔函数。 它首先解除绑定所有的jQuery事件ko.cleanNode方法不采取照顾。 我测试过的内存泄漏,它似乎工作得很好。

ko.unapplyBindings = function ($node, remove) {
    // unbind events
    $node.find("*").each(function () {
        $(this).unbind();
    });

    // Remove KO subscriptions and references
    if (remove) {
        ko.removeNode($node[0]);
    } else {
        ko.cleanNode($node[0]);
    }
};


Answer 3:

你可以尝试使用的是与结合淘汰赛提供: http://knockoutjs.com/documentation/with-binding.html的想法是使用一次申请绑定,并且只要你的数据发生变化,只需更新你的模型。

比方说你有一个顶层视图模型storeViewModel,由cartViewModel代表你的车,并在车中的项目清单 - 说cartItemsViewModel。

你会绑定顶层模式 - storeViewModel整个页面。 然后,你可以分开你的网页中,负责购物车或购物车的物品的部分。

让我们假设cartItemsViewModel结构如下:

var actualCartItemsModel = { CartItems: [
  { ItemName: "FirstItem", Price: 12 }, 
  { ItemName: "SecondItem", Price: 10 }
] }

该cartItemsViewModel可以在开始时是空的。

具体的步骤是这样的:

  1. HTML定义绑定。 分隔cartItemsViewModel结合。

       <div data-bind="with: cartItemsViewModel"> <div data-bind="foreach: CartItems"> <span data-bind="text: ItemName"></span> <span data-bind="text: Price"></span> </div> </div> <div data-bind="with: cartItemsViewModel"> <div data-bind="foreach: CartItems"> <span data-bind="text: ItemName"></span> <span data-bind="text: Price"></span> </div> </div> 
  2. 商店模型来自您的服务器(或以任何其他方式创建)。

    var storeViewModel = ko.mapping.fromJS(modelFromServer)

  3. 在你的顶层视图模型定义空模型。 然后,该模型的结构可与实际数据进行更新。

       storeViewModel.cartItemsViewModel = ko.observable(); storeViewModel.cartViewModel = ko.observable(); storeViewModel.cartItemsViewModel = ko.observable(); storeViewModel.cartViewModel = ko.observable(); 
  4. 绑定顶级视图模型。

    ko.applyBindings(storeViewModel);

  5. 当cartItemsViewModel对象可用,则分配给之前定义的占位符。

    storeViewModel.cartItemsViewModel(actualCartItemsModel);

如果你想清除车项目: storeViewModel.cartItemsViewModel(null);

淘汰赛将采取HTML的照顾 - 即当模型不为空和div的内容(一个与“用结合”)消失会出现。



Answer 4:

我要叫ko.applyBinding每次搜索点击按钮,过滤数据是从服务器返回,在这种情况下以下不使用ko.cleanNode为我工作。

我有经验,如果我们用模板替换的foreach,那么它应该在集合/ observableArray的情况下正常工作。

您可能会发现这种情况下非常有用。

<ul data-bind="template: { name: 'template', foreach: Events }"></ul>

<script id="template" type="text/html">
    <li><span data-bind="text: Name"></span></li>
</script>


Answer 5:

除了使用KO的内部功能和处理JQuery的毛毯事件处理去除的,一个更好的主意是使用withtemplate绑定。 当你做到这一点,KO重新创建DOM的一部分,所以它会自动得到清洁。 这也是推荐的方式,在这里看到: https://stackoverflow.com/a/15069509/207661 。



Answer 6:

我想这可能是更好地保持绑定的整个时间,并简单地更新与它相关的数据。 我就遇到了这个问题,并发现,仅仅使用呼叫.resetAll()方法中,我保持我的数据在阵列上是做到这一点的最有效途径。

基本上,你可以用它包含数据通过视图模型被渲染一些全局变量入手:

var myLiveData = ko.observableArray();

我花了一段时间来实现我不能只是做myLiveData一个正常的阵列-在ko.oberservableArray部分是非常重要的。

然后你就可以继续前进,做任何你想做的myLiveData 。 例如,做一个$.getJSON电话:

$.getJSON("http://foo.bar/data.json?callback=?", function(data) {
    myLiveData.removeAll();
    /* parse the JSON data however you want, get it into myLiveData, as below */
    myLiveData.push(data[0].foo);
    myLiveData.push(data[4].bar);
});

一旦你做到了这一点,你可以继续使用您的视图模型像往常一样适用绑定:

function MyViewModel() {
    var self = this;
    self.myData = myLiveData;
};
ko.applyBindings(new MyViewModel());

然后在HTML只使用myData像平时那样。

通过这种方式,你可以从任何一个功能myLiveData淤泥。 举例来说,如果你想每隔几秒钟更新,只是包装是$.getJSON线功能和调用setInterval就可以了。 你永远需要删除,只要你记住保持绑定myLiveData.removeAll(); 通车。

除非你的数据确实是巨大的,用户甚至不能够在重置阵列,然后加入最通用的数据传回在这两者之间发现的时间。



Answer 7:

我最近有内存泄漏问题,并且ko.cleanNode(element); 我不会做它- ko.removeNode(element); 没有。 JavaScript和Knockout.js内存泄漏-如何确保对象被销毁?



Answer 8:

你有没有想过这一点:

try {
    ko.applyBindings(PersonListViewModel);
}
catch (err) {
    console.log(err.message);
}

我因为在淘汰赛想出了这个,我发现这个代码

    var alreadyBound = ko.utils.domData.get(node, boundElementDomDataKey);
    if (!sourceBindings) {
        if (alreadyBound) {
            throw Error("You cannot apply bindings multiple times to the same element.");
        }
        ko.utils.domData.set(node, boundElementDomDataKey, true);
    }

所以对我来说它不是真的,它已经绑定的问题,它的错误并没有捕获和处理...



Answer 9:

我发现,如果视图模型包含了很多的div绑定清除的最好方法ko.applyBindings(new someModelView); 是使用: ko.cleanNode($("body")[0]); 这使您可以调用一个新的ko.applyBindings(new someModelView2); 动态无以前的视图模型的担心仍然被绑定。



文章来源: How to clear/remove observable bindings in Knockout.js?