挖空.js动态生成的 HTML 没有得到更新

Knockout.js dynamicly generated HTML not getting updates

本文关键字:更新 HTML js 动态 挖空      更新时间:2023-09-26

我有一个相当复杂的系统在后台工作,将尝试给出最简短和最短的例子:

我有一个PHP/HTML页面,它触发对服务器的Ajax调用并得到一个响应XML。基于XML,javascript动态地创建一堆DOM元素。XML还包含我映射到主页上存在的挖空视图模型的数据。

然而,元素没有得到更新,或者更确切地说是淘汰.js根本没有与它们交互(我会假设ko.applyBinding(model)是罪魁祸首。

这是我需要的: 1. 加载一个包含挖空.js 的 PHP 页面和一个视图模型对象。 2. 发送一个 AJAX 请求,该请求返回新数据以使用添加到页面中的新 HTML DOM 元素来更新模型。 3.有敲除.js跟踪这些新元素中的数据信息。

我看到的问题是ko.applyBinding(model)在HTML元素存在于DOM中之前被触发,因此它们永远不会被绑定,但是根本没有办法知道将添加哪些元素以及将从服务器中提取哪些数据,并且它必须保持动态。

我已经弄清楚,如果我可以重新应用绑定它会起作用(我认为),但尝试这样做会产生错误。我在其他几篇文章中读到,没有办法为整个文档重新应用绑定,但必须为每个元素单独完成,但是这些元素必须是 DOM 中的同级,这对我不起作用,因为它们需要嵌套。

对解决方案有什么想法吗?

编辑:做了一个JSFiddle示例,但是由于我不能包含挖空映射.js,它不起作用,所以我准备了.HTML文档并添加了所需的库(挖空.js和挖空映射.js),将它们全部链接在一起并上传到这里它是一个.rar文件,包含所有设置和库。

编辑2:下面还可以看到所需内容的简短预览:

var ViewModel = {
  buttonOneText: ko.observable("Button 1")
}
ko.applyBindings(ViewModel);
// IMAGINARY AJAX HAPPENS
// when this happens I need to add another button into the frameDiv and add it's data to the model.
document.getElementById("frameDiv").innerHTML += '<button type="button" data-bind="text: buttonTwoText"></button>'
ViewModel.buttonTwoText = "Button 2";
ko.applyBindings(ViewModel, document.getElementById("frameDiv"));
//				So far this works, and it is great!
//				If you comment out the rest of the JS code it will work perfectly
//				problem comes when you attempt to add a thrid element, because
//				even though "frameDiv" has no bind-data, it doesn't let you run it
//				again on that div.
document.getElementById("frameDiv").innerHTML += '<button type="button" data-bind="text: buttonThreeText"></button>'
ViewModel.buttonThreeText = "Button 3";
ko.applyBindings(ViewModel, document.getElementById("frameDiv"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="frameDiv">
  <button type="button" data-bind="text: buttonOneText"></button>
  <!-- The following element will be added VIA Javascript code -->
  <!--<button type="button" data-bind="text: buttonTwoText"></button>-->
</div>

您可以向ko.applyBindings提供第二个参数,该参数指定要将绑定应用到的顶级节点。您可以在您创建的任何节点上调用它,只要您没有将已绑定的节点放在它们下面。

下面是一个小示例脚本,其中包含一个例程,用于创建新的 DOM 节点、插入它并对其应用绑定。单击该按钮以执行例程。

parser = new DOMParser();
foo = 1;
vm = {
  makeNode: function() {
    var el = parser.parseFromString('<div data-bind="text:' + foo + '"></div>', "text/xml").childNodes[0];
    ++foo;
    document.getElementById('foo').appendChild(el);
    ko.applyBindings(vm, el);
  }
};
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div id="foo">
</div>
<button data-bind="click: makeNode">Add node</button>