淘汰 foreach 不会清除新虚拟机上的先前条目

2024-05-16

我有一个模态形式,其中有两个绑定到可观察数组的嵌套列表。

每次我单击按钮打开模式时,这两个嵌套列表都不会清除它们以前的数据,即使我为整个事物生成了一个全新的视图模型。我最终在这两个列表中得到了重复的(和三次的,等等)项目。

如何确保当我给这个东西一个新的视图模型时,它会清除以前的数据?

ViewModel 本身很好:我可以ko.toJS(self)在每个实例上,数据中的所有内容都是正确的。这是绑定的某种剩余物。

这是我对该特定区域的绑定:

<div class="notes-container" data-bind="visible: showNotesContainer">

    <label>Notes</label>
    <ul data-bind="foreach: noteGroups" class="question-list">                                
        <li>
            <span class="he-question-group" data-bind="text: name"></span>
            <ul class="he-question-list" data-bind="foreach: notes">
                <li><span data-bind="text: question"></span></li>
                <li><input type="text" data-bind="value: answer" /></li>
            </ul>
        </li>
    </ul>
</div>

这是我的“基础”虚拟机:

function hoursEntryVM(model) {

    var self = this;

    ...
    self.noteGroups = ko.observableArray(getNoteGroupsVMs(model.NoteGroups));
    ...

    var root = document.getElementById(model.rootElementId);
    ko.cleanNode(root)
    ko.applyBindings(self, root);

    return self;

    function getNoteGroupsVMs(noteGroupModel) {
        var notes = [];
        for (var i = 0; i < noteGroupModel.length; i++) {
            notes.push(new hoursNoteGroupVM(noteGroupModel[i]));
        }
        return notes;
    }       
}

在按钮上单击打开模式我有这样的东西:

$.ajax({
    url: '/mysource',
    success: function(data) {
        data.rootElementId = 'hours-entry-container';
        var vm = new window.myProj.hoursEntry.hoursEntryVM(data);
        console.log(ko.toJS(vm));
        myModal.Show();
    }
});

既然您自己找到了处理此问题的最佳方法(使用模板),但您表示您想知道发生了什么:

foreach在引擎盖下

foreach工作原理类似于就地模板绑定。这innerHTML与 绑定的元素foreach被视为模板字符串。

What cleanNode does not do

当你cleanNode,敲除不会“撤销”其绑定;它仅删除视图(HTML)和视图模型(js)之间的依赖关系。绑定上下文被删除。

这意味着,之后cleanNode,用作模板的内部 HTML 发生变化。

演示:

var source = [1, 2, 3];


var applyAndClean = function() {
  var el = document.querySelector("ul");

  console.log("Applying bindings using template:");
  console.log(el.innerHTML);

  ko.applyBindings(source, el);
  ko.cleanNode(el);
}

ko.applyBindings({
  onClick: applyAndClean
}, document.querySelector("button"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<button data-bind="click: onClick">apply and clean</button>

<ul data-bind="foreach: $data">
  <li data-bind="text: $data"></li>
</ul>

按下按钮应用固定器并随后进行清洁。控制台记录所使用的模板。第一次运行,模板包含one <li>不断重复three次。第二次运行,模板包含three <li>重复三次的元素。即:列表项的数量等于3^n for n = numer of times bindings are applied.

与的区别template binding

模板绑定不关心数据绑定元素中的内容。它只是丢弃所有innerHTML并将其替换为链接的模板。

再次,就像评论者所说,你永远不需要打电话cleanNode(也许在自定义绑定之外)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

淘汰 foreach 不会清除新虚拟机上的先前条目 的相关文章

随机推荐