带有Asp.Net核心ViewComponents的多个Knockout视图模型

我有简单的FullName viewcomponent与淘汰赛视图模型里面:

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>

<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());
</script>

当我调用这个组件时,像@(await Component.InvokeAsync("FullName")) ,它很好用。

但是,当我试图多次调用此组件时:

@(await Component.InvokeAsync("FullName"))
@(await Component.InvokeAsync("FullName"))
@(await Component.InvokeAsync("FullName"))
//etc...

我有一个错误,Knockout不能应用多个相同的绑定。

那么,如何将包含Knockout视图模型的多个ViewComponents包含到一个页面中呢?


在你的代码中,你为每个添加的组件调用一次applyBindings ,并且Knockout不会让你绑定不止一次的东西,除非你先删除绑定(按照Matt.kaaj的评论)。

话虽如此,我认为如果你想在多个地方重复使用你的视图模型,你应该看看你的绑定范围。

完全公开 - 我不太了解asp.net,它是ViewComponents ,所以如果语法不正确,我很抱歉,但它似乎支持传入参数。 看起来你可以通过改变你的组件定义来解决这个问题:

<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的.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的文档就绪函数进行了包装,以便您可以安全地假定DOM已准备好进行操作。 只要确保您的脚本也包含在您的页面中,就像现在它与视图组件分开。

链接地址: http://www.djcxy.com/p/83519.html

上一篇: Multiple Knockout viewmodels with Asp.Net Core ViewComponents

下一篇: How to set Attribute value for a class with multiple items