两个独立的模型 - 您不能将绑定多次应用于同一个元素

Posted

技术标签:

【中文标题】两个独立的模型 - 您不能将绑定多次应用于同一个元素【英文标题】:Two separate models - You cannot apply bindings multiple times to the same element 【发布时间】:2017-04-04 15:11:30 【问题描述】:

我有一个 MVC 应用程序,它有一个内容页面,链接到一个视图模型。它运作良好。但是,一旦我将视图模型添加到我的内容页面(在我的布局中生成),我就会收到错误消息:

您不能对同一个元素多次应用绑定。

我已经创建了“Sections”并尝试绑定到该部分,如下所示。

// 在我的布局页面中。

<div class='liveExample' id="sectionOne">   
    <p>First name: <input data-bind='value: firstName' /></p> 
    <p>Last name: <input data-bind='value: lastName' /></p> 
    <h2>Hello, <span data-bind='text: fullName'> </span>!</h2>  
</div>

// 在我的索引(内容)页面中。

<div class='liveExample' id="sectionTwo">   
    <p>First name: <input data-bind='value: firstName' /></p> 
    <p>Last name: <input data-bind='value: lastName' /></p> 
    <h2>Hello, <span data-bind='text: fullName'> </span>!</h2>  
</div>

还有代码:

// 在我的 _Layout 页面中: ko.applyBindings(new ViewModel1("Planet", "Earth"), $("#sectionOne")[0]); // 这使得 Knockout 开始工作

// 在我的索引页面中: ko.applyBindings(new ViewModel2("Planet", "Earth"), $("#sectionTwo")[0]); // 这使得 Knockout 开始工作

这是一个 jsfiddle

https://jsfiddle.net/4fe2f6mL/1/

我无法创建一个主视图模型,将上面的两个模型作为子视图,因为 ko.applyBindings 位于单独的 cshtml 文件中。

我怎样才能让它工作,因为我的布局有一个视图模型(在导航栏中驱动菜单、登录、注册和“欢迎,用户名”类型的东西)

【问题讨论】:

我不确定您面临什么问题,但我已经在没有 jquery 的情况下更新了您的 jsfiddle 并且结果正常:jsfiddle.net/Salmin/7tozbtj8/1 【参考方案1】:

您链接的示例有效,因为数据绑定元素是兄弟。当存在 parent-child 结构时,您无法轻松地将 child 绑定到与 parent 不同的视图模型,仅使用 ko.applyBindings

使用部分 .cshtml 文件和 Razor 进行模板有时会与 Knockout 自己的模板功能发生冲突...就个人而言,我倾向于只在部分中定义 Knockout templates 并使用 foreachwith 绑定来获取我的要渲染的视图。

脏修复

目前一个快速而肮脏的修复方法可能是创建一个自定义绑定,在 DOM 树的一部分中禁用绑定:

ko.bindingHandlers.stopBinds = 
  init: function() 
    return  controlsDescendantBindings: true    
  


ko.virtualElements.allowedBindings.stopBinds = true;

// In your main js you bind the parent
var parent = document.getElementById("parent");
ko.applyBindings( test: "Parent value" , parent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div id="parent">
    <p data-bind="text: test"></p>

    <!-- start of your partial: -->

    <!-- ko stopBinds -->
      <div id="child" >
        <p data-bind="text: test"></p>
      </div>  
      <script>
        var child = document.getElementById("child");
        ko.applyBindings( test: "Child value" , child);
      </script>
    <!-- /ko -->
  
    <!-- end of your partial -->
</div>

稍微好一点的修复

ko.bindingHandlers.stopBinds = 
  init: function() 
    return  controlsDescendantBindings: true    
  


ko.virtualElements.allowedBindings.stopBinds = true;

// Expose the main vm
window.myVM = 
  test: "Parent value",
  childVM: ko.observable(null)
;

// Bind to document
$(document).ready(function() 
  ko.applyBindings(window.myVM);
  
  // Check if any callbacks have been registered and run them
  window.callbacks.forEach(function(cb) 
    cb();
  );
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<div id="parent">
    <p data-bind="text: test"></p>

    <!-- start of your partial: -->
      <div id="child" data-bind="with: childVM">
        <p data-bind="text: test"></p>
      </div>  
      <script>
          // Register a callback
          window.callbacks = window.callbacks || [];
          window.callbacks.push(function() 
            window.myVM.childVM( test: "Child value" );
          );
      </script>
    <!-- end of your partial -->
</div>

【讨论】:

谢谢。那么布局部分会是一个模板,而其余部分 - 正常吗?还是说每个视图模型都属于一个模板?在整个应用程序中。

以上是关于两个独立的模型 - 您不能将绑定多次应用于同一个元素的主要内容,如果未能解决你的问题,请参考以下文章

侧页敲除导致您不能多次将绑定应用于同一元素

Knockout.js v2.3.0 错误“您不能将绑定多次应用于同一元素”

在淘汰赛中将绑定应用于多个元素

更新 ViewModel 时如何防止 Kendo UI Grid 多次重新绑定

修复 JQM ajax 单页导航上的淘汰多个绑定

Spring Cloud Stream教程编程模型