在您的代码中,您为每个添加的组件调用一次applyBindings,并且 Knockout 不会让您多次绑定某些内容,除非您首先删除绑定(根据 Matt.kaaj 的评论)。
话虽如此,如果您想在多个地方重用您的视图模型,我认为您应该查看scoping your bindings。
完全披露 - 我对 asp.net 及其 ViewComponents 了解不多,所以如果语法不正确,我们深表歉意,但它们似乎支持 passing in parameters。看起来您可以通过将组件定义更改为以下内容来解决此问题:
<div id=${idThatIPassIn}>
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
</div>
<script>
function AppViewModel() {
this.firstName = ko.observable("");
this.lastName = ko.observable("");
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
}
ko.applyBindings(new AppViewModel(), document.getElementById('${idThatIPassIn}'));
</script>
然后初始化:
@(await Component.InvokeAsync("FullName"), new { idThatIPassIn = "name-1" })
@(await Component.InvokeAsync("FullName"), new { idThatIPassIn = "name-2" })
@(await Component.InvokeAsync("FullName"), new { idThatIPassIn = "name-3" })
这样,每次您告诉 knockout 应用绑定时,该绑定都会被上下文化为一个包装您的 <p> 元素的 div,因此您最终不会尝试重新绑定已经绑定的内容。
或者,您可以分配一个随机的任意 ID 并绑定到该 ID,而不是传入一个 ID。无论哪种情况,请将您的 applyBindings 调用范围限定为一个元素。
编辑 - 您提到不想通过 ID 绑定。而是尝试使用一个类和jQuery's .each 方法。比如:
<div class="name-block">
<p>First name: <strong data-bind="text: firstName"></strong></p>
<p>Last name: <strong data-bind="text: lastName"></strong></p>
<p>First name: <input data-bind="value: firstName" /></p>
<p>Last name: <input data-bind="value: lastName" /></p>
<p>Full name: <strong data-bind="text: fullName"></strong></p>
</div>
按照您当前的方式初始化:
@(await Component.InvokeAsync("FullName"))
@(await Component.InvokeAsync("FullName"))
@(await Component.InvokeAsync("FullName"))
然后在另一个单独的 .js 中包含,添加:
<script>
//I'm assuming that jQuery is available
$(document).ready(function(){
function AppViewModel() {
this.firstName = ko.observable("");
this.lastName = ko.observable("");
this.fullName = ko.computed(function() {
return this.firstName() + " " + this.lastName();
}, this);
}
$(".name-block").each(function(index, obj){
ko.applyBindings(new AppViewModel(), obj);
});
});
</script>
这样,您的视图模型只定义一次,您的绑定将应用于每个具有“名称块”类的单独 div。
我还将整个过程封装在 jQuery 的 document ready 函数中,因此您可以放心地假设 DOM 已准备好进行操作。只需确保您的脚本也包含在您的页面中,因为现在它已与视图组件分开。