淘汰赛foreach不清除新VM上的先前条目 [英] Knockout foreach not clearing previous entries on new VM

查看:47
本文介绍了淘汰赛foreach不清除新VM上的先前条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a modal form with two nested lists bound to observable arrays.

每次我单击按钮打开模态时,这两个嵌套列表都不会清除它们以前的数据,即使通过我为整个对象生成了一个全新的视图模型也是如此.最后,我发现了这两个列表中的重复项(重复项,等等).

Each time I click the button to open the modal, these two nested lists aren't clearing their previous data, even through I generate a brand new viewmodel for the whole thing. I wind up with duplicated (and triplicated, etc...) items in these two lists.

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

How can I ensure that when I give this thing a new viewmodel, it clears out the previous data?

ViewModel本身很好:我可以在每个实例上ko.toJS(self)这样做,并且数据中的所有内容都是正确的.这是绑定中的剩余部分.

The ViewModel itself is fine: I can ko.toJS(self) that on each instance and everything's correct in the data. It's some sort of leftover from the bindings.

这是该特定区域的绑定:

Here's my bindings for that particular area:

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

这是我的基本"虚拟机:

Here's my "base" VM:

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

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

On the button click for opening the modal I have something like this:

$.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();
    }
});

推荐答案

由于您已经找到了自己处理(使用模板)的最佳方法,但是您表示想知道正在发生的事情:

Since you figured out the best way to handle this (use templates) yourself, but you stated you'd like to know what was happening:

foreach的作用类似于就地模板绑定.与foreach绑定的元素的innerHTML被视为模板字符串.

foreach works like an in-place template binding. The innerHTML of the element bound with foreach is treated as a template string.

cleanNode时,敲除不会撤消"其绑定;它仅删除视图(HTML)和视图模型(js)之间的依赖关系.绑定上下文被删除.

When you cleanNode, knockout does not "undo" its bindings; it only removes the dependencies between view (HTML) and viewmodel (js). The binding context is deleted.

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

This means that, after cleanNode, the inner HTML that is used as a template changes.

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>,该重复次数为 3 次.第二次运行时,模板包含三个 <li>元素,这些元素将重复三次.即:列表项的数量等于n = numer of times bindings are applied3^n.

Press the button to apply bindings and clean after. The console logs the template used. The first run, the template contains one <li> that gets repeated three times. The second run, the template contains three <li> elements which get repeated three times. I.e.: the number of list items equals 3^n for n = numer of times bindings are applied.

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

The template binding doesn't care what's in the data-bound element. It simply discards all innerHTML and replaced it with the template linked.

同样,如评论员所述,您永远不需要调用cleanNode(也许在自定义绑定之外).

Again, like the commenter stated, you should never need to call cleanNode (outside of, maybe, a custom binding).

这篇关于淘汰赛foreach不清除新VM上的先前条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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