如何在Knockout.js中清除/删除可观察的绑定?

awj*_*awj 113 javascript knockout.js

我正在将功能构建到用户可以多次执行的网页上.通过用户的操作,使用ko.applyBindings()创建对象/模型并将其应用于HTML.

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

到现在为止还挺好.

当我通过创建第二个对象/模型并调用ko.applyBindings()重复此步骤时,我遇到两个问题:

  1. 标记显示前一个对象/模型以及新对象/模型.
  2. 发生与对象/模型中的某个属性相关的javascript错误,尽管它仍然在标记中呈现.

为了解决这个问题,在第一次传递之后,我调用jQuery的.empty()来删除包含所有数据绑定属性的模板化HTML,这样它就不再存在于DOM中了.当用户启动第二次传递的过程时,数据绑定的HTML将重新添加到DOM.

但就像我说的那样,当HTML重新添加到DOM并重新绑定到新的对象/模型时,它仍然包含来自第一个对象/模型的数据,我仍然得到不会发生的JS错误在第一次通过期间.

结论似乎是Knockout坚持这些绑定属性,即使从DOM中删除了标记.

所以我正在寻找的是从Knockout中删除这些绑定属性的方法; 告诉淘汰赛,不再有可观察的模型.有没有办法做到这一点?

编辑

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

mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
Run Code Online (Sandbox Code Playgroud)

一旦用户在模型上做了一些选择,就会将相同的对象发回服务器,从DOM中删除数据绑定的HTML,然后我有以下JS

mn.AccountCreationModel = null;
Run Code Online (Sandbox Code Playgroud)

当用户希望再次执行此操作时,重复所有这些步骤.

我担心代码太"参与"了jsFiddle演示.

Kod*_*hor 169

您是否尝试在DOM元素上调用knockout的clean节点方法来处置内存绑定对象?

var element = $('#elementId')[0]; 
ko.cleanNode(element);
Run Code Online (Sandbox Code Playgroud)

然后再次使用新视图模型对该元素应用knockout绑定将更新视图绑定.

  • 这工作 - 谢谢.但是,我无法找到有关此方法的任何文档. (33认同)
  • 你找不到它.我在ko效用函数上搜索了高低文档,但都没有.这篇博文是你能找到的最接近的东西,但它只涵盖了ko.utils的成员:http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html (2认同)

Mic*_*pas 31

对于我正在研究的项目,我编写了一个ko.unapplyBindings接受jQuery节点和remove boolean 的简单函数.它首先解除所有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]);
    }
};
Run Code Online (Sandbox Code Playgroud)

  • 你的解决方案也不会取消绑定所有其他事件绑定吗?是否有可能只删除ko的事件处理程序? (4认同)

小智 12

你可以尝试使用knockout提供的with binding:http: //knockoutjs.com/documentation/with-binding.html 这个想法是使用apply bindings一次,每当你的数据发生变化时,只需更新你的模型.

假设您有一个顶级视图模型storeViewModel,您的购物车由cartViewModel表示,以及该购物车中的项目列表 - 比如cartItemsViewModel.

您可以将顶级模型 - storeViewModel绑定到整个页面.然后,您可以分离页面中负责购物车或购物车商品的部分.

让我们假设cartItemsViewModel具有以下结构:

var actualCartItemsModel = { CartItems: [
  { ItemName: "FirstItem", Price: 12 }, 
  { ItemName: "SecondItem", Price: 10 }
] }
Run Code Online (Sandbox Code Playgroud)

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>
      
    
  2. 商店模型来自您的服务器(或以任何其他方式创建).

    var storeViewModel = ko.mapping.fromJS(modelFromServer)

  3. 在顶级视图模型上定义空模型.然后可以使用实际数据更新该模型的结构.

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

    ko.applyBindings(storeViewModel);

  5. 当cartItemsViewModel对象可用时,将其分配给先前定义的占位符.

    storeViewModel.cartItemsViewModel(actualCartItemsModel);

如果您想清除购物车物品: storeViewModel.cartItemsViewModel(null);

Knockout将处理html - 即当模型不为空时它将出现,div的内容(带有"with binding"的那个)将消失.


aam*_*jad 9

我必须在每次搜索按钮单击时调用ko.applyBinding,并且过滤后的数据从服务器返回,在这种情况下,在不使用ko.cleanNode的情况下为我工作.

我经历过,如果我们用模板替换foreach,那么它应该在collections/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>
Run Code Online (Sandbox Code Playgroud)


Shi*_*hah 6

而不是使用KO的内部函数和处理JQuery的全局事件处理程序删除,更好的想法是使用withtemplate绑定.当你这样做时,ko重​​新创建DOM的那一部分,因此它会自动被清理.这也是推荐的方式,请参见此处:https://stackoverflow.com/a/15069509/207661.