Knockout.js的cleanNode没有取消绑定事件

时间:2014-12-11 23:31:02

标签: javascript knockout.js

我有一个类似数据的模态弹出窗口,需要清除绑定。 The answer for the highest rating说要使用knockout的清洁节点方法

以下是(手写)代码段:

var ViewModel = function(v) {
   var self = this;
   self.Foo = ko.observable(v.Foo);
   self.Bar = ko.observable(v.Bar);
   self.Stuffs = ko.observableArray([]);
   self.AddStuffs = function() { ... }
}

var myViewModel = new ViewModel({Foo : "", Bar: "" });
var myModal= document.getElementById("myModal");
ko.cleanNode(myModal);
ko.applyBindings(myViewModel, myModal);

HTML:

<div id="myModal">
<a href="#" data-bind="click:$root.AddStuff">my link</a>
<table>
    <tbody data-bind="foreach:Stuffs ">
        <tr>
            <td><span data-bind="text:Interval"></span></td>
        </tr>
    </tbody>
</table>
</div>

当我第一次打开模态时,一切似乎都正常。但是this answer说cleanNode是错误的解决方案,因为cleanNode是淘汰的内部清理。它不会清理事件处理程序,因此当我的模态关闭并再次打开并单击AddStuff的链接时,该事件将被调用n次(n =我打开弹出窗口的次数)。提到的解决方案是“更好的模式是使用或围绕一个部分使用模板绑定,并允许使用新绑定重新渲染它。”但是没有关于如何做的任何后续行动。

我不确定“模板”是什么意思,但我tried adding "with"绑定我用于模态的div,并且在一次链接点击时仍然会多次调用事件。有人可以帮我找到一种让这种方法正常工作的方法吗?

1 个答案:

答案 0 :(得分:1)

我不认为cleanNode是你想要的。一般来说,你不应该清理节点并重新应用绑定,除非你做了一些非常不寻常的事情,我不认为你是这样。您只是想更改DOM的特定部分绑定的ViewModel,对吗?

我只需要创建一个可观察的视图,该视图保存模式应绑定到的ViewModel,然后根据该模板编写模板。

var ModalViewModel = function(v) {
   var self = this;
   self.Foo = ko.observable(v.Foo);
   self.Bar = ko.observable(v.Bar);
   self.Stuffs = ko.observableArray([]);
   self.AddStuffs = function() { ... }
}

var modalViewModel = new ModalViewModel({Foo : "Foo", Bar: "Bar" });

var viewModel = {
    modal: ko.observable(modalViewModel)
};

var myModal= document.getElementById("myModal");

ko.applyBindings(myViewModel, myModal);

请注意,实际绑定到模式的viewModel永远不会更改,但包含一个子视图模型。上述逻辑应该只执行一次,然后更改或删除模态,可以修改viewModel.modal observable。

然后你的模板看起来像

<div id="myModal" data-bind="with: modal">
<a href="#" data-bind="click:AddStuff">my link</a>
<table>
    <tbody data-bind="foreach:Stuffs ">
        <tr>
            <td><span data-bind="text:Interval"></span></td>
        </tr>
    </tbody>
</table>
</div>

(唯一的变化是with: modal部分,删除了不必要的$root

这是一个展示此工作的简约版本:http://jsfiddle.net/260wypyk/