ko.cleanNode 移除 jQuery .on("focusout") 事件

ko.cleanNode removes the jQuery .on("focusout") event

我正在使用 Knockout JS 应用程序。我在使用 ko.cleanNode(node) 时遇到问题,它删除了 focusout 客户端事件。即,在调用 cleanNode 方法之前,focusOut 在文本框上正常工作。在那之后 focusOut 事件没有被触发。我检查了很多堆栈溢出问题,我只是找到了这个删除的原因,没有找到任何替代解决方案。这是我的代码。

$("#btn").click(function() {
  viewModel = {
    nValue: ko.observable(10)
  }
  ko.cleanNode(document.getElementById("txt"));
  ko.applyBindings(viewModel, document.getElementById("txt"));
});
ko.applyBindings({
  nValue: ko.observable(100)
});
$("#txt").on("focusout", function() {
  alert("focusOut");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="text" id="txt" data-bind="value: nValue" />
<input type="button" id="btn" value="cleannode" />

来自 disposal logic 上的 Knockout 文档:

When removing an element, Knockout runs logic to clean up any data associated with the element. As part of this logic, Knockout calls jQuery’s cleanData method if jQuery is loaded in your page. In advanced scenarios, you may want to prevent or customize how this data is removed in your application. Knockout exposes a function, ko.utils.domNodeDisposal.cleanExternalData(node), that can be overridden to support custom logic. For example, to prevent cleanData from being called, an empty function could be used to replace the standard cleanExternalData implementation

因此,覆盖文档中提到的 cleanExternalData

ko.utils.domNodeDisposal.cleanExternalData = function () {
    // Do nothing. Now any jQuery data associated with elements will
    // not be cleaned up when the elements are removed from the DOM.
};

$("#btn").click(function() {
  viewModel = {
    nValue: ko.observable(10)
  }
  ko.cleanNode(document.getElementById("txt"));
  ko.applyBindings(viewModel, document.getElementById("txt"));
});

ko.applyBindings({
  nValue: ko.observable(100)
});

$("#txt").on("focusout", function() {
  alert("focusOut");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="text" id="txt" data-bind="value: nValue" />
<input type="button" id="btn" value="cleannode" />


查看您的代码,如果您的意图只是在单击时更新视图模型的 observable 并添加 focusOut 事件处理程序,则不需要 cleanNodeapplyBindings() 或完全使用 jquery。您可以像这样使用 knokcout 的 click and event 绑定:

var viewModel = function() {
  var self = this;

  self.nValue = ko.observable(100);

  self.increment = function() {
    self.nValue(self.nValue() + 1);
  }

  self.focusOut = function() {
    alert("Focus Out");
  }
};

ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="text" id="txt" data-bind="value: nValue, event: { focusout: focusOut }" />
<input type="button" id="btn" value="increment" data-bind="click: increment" />