【问题标题】:Multiple Knockout viewmodels with Asp.Net Core ViewComponents具有 Asp.Net Core ViewComponents 的多个 Knockout 视图模型
【发布时间】:2017-02-16 15:50:38
【问题描述】:

我有一个简单的 FullName 视图组件,里面有淘汰视图模型:

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 包含在一个页面中?

【问题讨论】:

  • 在淘汰赛中,您不能再次将绑定应用于same 元素。如果您真的想这样做,请在再次使用“applyBindings”之前删除绑定。 ko.cleanNode($element).

标签: c# mvvm knockout.js asp.net-core


【解决方案1】:

在您的代码中,您为每个添加的组件调用一次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 应用绑定时,该绑定都会被上下文化为一个包装您的 &lt;p&gt; 元素的 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 已准备好进行操作。只需确保您的脚本也包含在您的页面中,因为现在它已与视图组件分开。

【讨论】:

  • 我一直在考虑这种方式,但是它需要很多辅助代码,用于创建唯一的id,这就是我想要省略的方式。
  • 所以如果我对您的理解正确,您不想管理分配给您的 div 的唯一 ID?如果是这样的话,一个类然后分别对每个类应用绑定怎么样?
  • 是的,你理解正确。您能否提供一个将绑定应用于每个类的示例?但是如果我们类,它们不是个体的,似乎我们会在多个视图模型中遇到相同的错误,不是吗?
  • @YuriyN。当然。我假设你有 jQuery 可用,因为它会使诸如迭代类和检查 dom 就绪性之类的事情变得更加容易。
  • 太好了,这就是我需要的!总而言之,我需要在其中定义我的ViewComponent 类 div,然后在该视图组件调用的页面上,我包含绑定 javascript。我说的对吗?
猜你喜欢
  • 1970-01-01
  • 2012-08-04
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2016-12-21
  • 2014-01-21
  • 1970-01-01
相关资源
最近更新 更多