Knockout.js 淘汰foreach未清除新VM上以前的条目

Knockout.js 淘汰foreach未清除新VM上以前的条目,knockout.js,Knockout.js,我有一个模态形式,两个嵌套列表绑定到可观察数组 每次单击按钮打开模式时,这两个嵌套列表都不会清除它们以前的数据,即使我为整个事件生成了一个全新的viewmodel。我在这两个列表中得到了重复的(和三次重复的,等等)项 我如何确保当我给它一个新的viewmodel时,它会清除以前的数据 ViewModel本身很好:我可以ko.toJS(self)在每个实例上使用它,并且数据中的所有内容都是正确的。这是一些从绑定中遗留下来的东西 以下是我对该特定区域的绑定: <div class="notes

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

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

我如何确保当我给它一个新的viewmodel时,它会清除以前的数据

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>

我能够通过击倒来完成期望的行为:


笔记

  • 我仍然很想知道为什么最初的尝试是这样的。

    因为你自己找到了处理这个问题的最佳方法(使用模板),但是你说你想知道发生了什么:

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

    什么
    cleanNode
    不起作用 当您
    cleanNode
    时,knockout不会“撤消”其绑定;它只删除视图(HTML)和视图模型(js)之间的依赖关系。绑定上下文被删除

    这意味着,在
    cleanNode
    之后,用作模板的内部HTML会发生更改

    示范:
    var-source=[1,2,3];
    var applyAndClean=函数(){
    var el=文件查询选择器(“ul”);
    log(“使用模板应用绑定:”);
    log(el.innerHTML);
    ko.应用绑定(来源,el);
    k.清洁节点(el);
    }
    ko.applyBindings({
    onClick:applyAndClean
    },document.querySelector(“按钮”)
    
    
    涂抹并清洁
    

    切勿在视图模型代码中调用
    applyBinding
    (或
    cleanNode
    )。视图模型应该只表示数据和行为,而不是将自身应用于文档。理想情况下,您需要这样的内容:
    var vm=new hoursEntryVM()然后
    ko.applyBindings(vm)
    @haim770-谢谢,注意到了。太好了!非常感谢。
    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();
        }
    });
    
    <div class="notes-container" data-bind="visible: showNotesContainer">
        <label>Notes</label>
    
        <ul class="question-list" data-bind="template: { name: 'hours-noteGroups-template', foreach: noteGroups }"></ul>
    
        <script type="text/html" id="hours-noteGroups-template">
            <li><span class="he-question-group" data-bind="text: name"></span>
                <ul id="he-notes-list" 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>
        </script>
    
    </div>