淘汰赛foreach不清除新VM上的先前条目 [英] Knockout foreach not clearing previous entries on new 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 applied
的3^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屋!