Knockout.js 的 cleanNode 不会解除绑定事件 [英] Knockout.js's cleanNode does not unbind events

查看:23
本文介绍了Knockout.js 的 cleanNode 不会解除绑定事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含类似数据的模式弹出窗口,需要清除绑定.评分最高的答案说使用knockout的clean node方法

以下是(手写的)代码片段:

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:

<a href="#" data-bind="click:$root.AddStuff">我的链接</a><表格><tbody data-bind="foreach:Stuffs"><tr><td><span data-bind="text:Interval"></span></td></tr></tbody>

当我第一次打开模态时,一切似乎都正常.但是 这个答案 说 cleanNode 是不正确的解决方案,因为 cleanNode 是淘汰赛的内部清理.它不会清理事件处理程序,因此当我的模态关闭并再次打开并单击 AddStuff 的链接时,该事件被调用 n 次(n = 我打开弹出窗口的次数).提到的建议解决方案是更好的模式是使用 with 或模板绑定围绕一个部分,并允许它使用新绑定重新呈现."但也没有跟进如何做.

我不确定他所说的模板"是什么意思,但我尝试添加with" 绑定我用于模态的 div,单击链接时仍会多次调用事件.有人可以帮我找到一种方法来使这项工作正常进行吗?

解决方案

我认为 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 = {模态:ko.observable(modalViewModel)};var myModal= document.getElementById("myModal");ko.applyBindings(myViewModel, myModal);

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

然后你的模板看起来像

<a href="#" data-bind="click:AddStuff">我的链接</a><表格><tbody data-bind="foreach:Stuffs"><tr><td><span data-bind="text:Interval"></span></td></tr></tbody>

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

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

I have a modal popup with similar data and need the bindings cleared. The answer for the highest rating says to use knockout's clean node method

Here are (handwritten) code snippets:

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>

When I first open the modal, everything seems to work okay. But this answer says cleanNode is the incorrect solution due to cleanNode being knockout's internal cleanup. It doesn't clean up event handlers, so when my modal is closed and opened again and I click the link for AddStuff, the event gets called n times (n = how many times I opened the popup). The proposed solution mentioned was "A better pattern is to use with or the template binding around a section and allow it to be re-rendered with the new bindings." but there was no followup on how to do either.

I'm not sure what he means by "template" but I tried adding "with" to bind my div that I use for the modal and events are still being called multiple times on one link click. Can someone help me find a way to get this working right?

解决方案

I don't think cleanNode is what you want. Generally speaking, you shouldn't need to be cleaning nodes and reapplying bindings unless you're doing something very out of the ordinary, which I don't think you are. You simply want to change the ViewModel that that particular section of the DOM is bound to, correct?

I'd simply make an observable that holds the ViewModel that the modal should be bound to, and then write your template based on that.

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);

Note that the viewModel that is actually bound to the modal never changes, but contains a sub-viewModel that does. The above logic should be executed exactly once, then to change or remove the modal, the viewModel.modal observable can be modified.

Then your template would look like

<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 the only change being the with: modal part, and the removal of an unnecessary $root)

Here's a minimalistic version that demonstrates this working: http://jsfiddle.net/260wypyk/

这篇关于Knockout.js 的 cleanNode 不会解除绑定事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆