78

我刚刚升级到 Knockout.js 2.3.0,现在我收到了这个错误:

You cannot apply bindings multiple times to the same element.

我没有进入 2.2.1。

我从我的 MVC 控制器获取部分视图,并在单击href. 当我第二次单击链接以获取部分视图时,会发生该错误。我正在多次这样做。

有没有办法清除它并避免抛出新的错误?

这是我的代码:

$.get(url + "GetAssignedCompaniesView?layoutId=" + layoutId + "&noCache=" + new Date().getMilliseconds(), function (result) {
    $("#editAssignedPartial").html($(result));
    showEditAssignedArea(true);
    $(window.document).ready(function () {
        // error is thrown here
        ko.applyBindings(self, window.document.getElementById("editAssigned"));
        $("#layoutId").attr("value", layoutId);
        updateTypeHiddenElement.attr("value", "companies");
    });
});

这是我的 HTML:

<div id="area1">
    <!-- grid here with links -->
</div>
<div id="editAssignedPartial"></div>
$(document).ready(function () {
    'use strict';
    var vm = new Vm();
    ko.applyBindings(vm, document.getElementById("area1"));
});
4

13 回答 13

101

您需要在再次使用之前删除绑定applyBindings

ko.cleanNode($element[0]);
于 2013-07-17T22:57:24.077 回答
30

以下是可能发生的引发此异常的事情。假设你有:

ko.applyBindings(myViewModel1, document.getElementById('element1'));
...
ko.applyBindings(myViewModel2, document.getElementById('element2'));

现在,当两者都不存在时,您将收到错误消息#element1#element2原因是当没有找到Knockout 时,它会作为根元素applyBindings返回。现在它尝试在身体上应用两次绑定......document.body#element1#element2

如果你问我,这不是淘汰赛的一个很好的后备。我宁愿有一个明确的错误消息,即 DOM 中不存在该元素(尚)。

于 2015-03-05T08:29:50.563 回答
13

永远不要对视图多次应用绑定。在 2.2 中,该行为未定义,但仍不受支持。在 2.3 中,它现在正确显示错误。使用淘汰赛时,目标是对页面上的视图应用一次绑定,然后使用对视图模型上的可观察对象的更改来更改页面上视图的外观和行为。

于 2013-07-17T22:35:00.580 回答
13

对于上述解决方案,有两件事很重要:

  1. 应用绑定时,需要指定范围(元素)!!

  2. 清除绑定时,您必须指定与作用域完全相同的元素。

代码如下

标记

<div id="elt1" data-bind="with: data">
    <input type="text" data-bind="value: text1" >
</form>

绑定视图

var myViewModel = {
  "data" : {
    "text1" : "bla bla"
  }
}:

Javascript

ko.applyBindings(myViewModel, document.getElementById('elt1'));

清除绑定

ko.cleanNode(document.getElementById('elt1'));
于 2014-09-16T14:47:04.433 回答
9

这个问题有很多很好的答案,但我有一个新手答案。

我发现我不小心在两个地方添加了相同的脚本,它试图绑定两次。所以在你拔头发之前,一定要检查这个问题。

于 2014-09-28T02:30:14.930 回答
5

如果您一遍又一遍地重用一个元素(在我的例子中是一个 Bootstrap 模式对话框),那么ko.applyBindings(el)多次调用会导致这个问题。

而是像这样做一次:

if (!applied) {
    ko.applyBindings(el);
    applied = true;
}

或者像这样:

var apply = function (viewModel, containerElement) {
    ko.applyBindings(viewModel, containerElement);
    apply = function() {}; // only allow this function to be called once.
}

PS:如果您使用映射插件并将您的 JSON 数据转换为 observables,这可能会更频繁地发生在您身上。

于 2014-11-11T04:05:29.487 回答
5

我终于通过返回绑定处理程序{ controlsDescendantBindings: true }的功能解决了我的问题。init看到这个

于 2015-05-28T09:10:25.567 回答
2

更新的答案

现在我们可以使用dataFor()来检查绑定是否已应用,我宁愿检查数据绑定,而不是cleanNode()and applyBindings()

像这样:

var koNode = document.getElementById('formEdit');
var hasDataBinding = !!ko.dataFor(koNode);
console.log('has data binding', hasDataBinding);
if (!hasDataBinding) { ko.applyBindings(vm, koNode);}

原始答案。

已经有很多答案了!

首先,假设我们需要在一个页面中进行多次绑定是相当普遍的。比如说,我在 Bootstrap 模式中有一个表单,它将一次又一次地加载。许多表单输入具有双向绑定。

我通常采取简单的方法:每次在绑定之前清除绑定。

var koNode = document.getElementById('formEdit');
ko.cleanNode(koNode);
ko.applyBindings(vm, koNode);

只要确保这里koNode是必需的,因为,ko.cleanNode()需要一个节点元素,即使我们可以在ko.applyBinding(vm).

于 2016-05-25T18:20:38.703 回答
1

由于不同的原因,我发生了这个错误。

我为希望出现在页面顶部和底部的保存/取消按钮创建了一个模板。当我在一个元素中定义我的模板时,它一开始就起作用了……但后来我听说你可以选择用普通元素<script type="text/html">创建一个模板。<div>

(这对我来说效果更好,因为我使用的是 ASP.NET MVC,并且@variableName在运行时没有从元素内部执行我的 Razor 语法<script>。所以通过改为 a <div>,我仍然可以让 MVC Razor 引擎在我的内部生成 HTML页面加载时的 Knockout.js 模板。)

在我将模板更改为使用 a<div>而不是<script>元素后,我的代码看起来像这样......在 IE 10 上运行良好。但是,后来当我在 IE 8 上测试它时,它抛出了错误:

You cannot apply bindings multiple times to the same element

HTML:

<div id="mainKnockoutDiv" class="measurementsDivContents hourlyMeasurements">

  <div id="saveButtons_template" style="display: none;">
    ... my template content here ...
  </div>

  <!--ko template: { name: 'saveButtons_template' } -->
  <!--/ko-->

  Some_HTML_content_here....

  <!--ko template: { name: 'saveButtons_template' } -->
  <!--/ko-->

</div>

JavaScript:

ko.applyBindings(viewModel, document.getElementById('mainKnockoutDiv'));

解决方案

我所要做的就是将我saveButtons_template <div>的底部移到底部,这样它就在mainKnockoutDiv. 这为我解决了这个问题。

我想 Knockout.js 试图<div>多次绑定我的模板,因为它位于applyBindings目标区域内......并且没有使用<script>元素......并且被引用为模板。

于 2014-07-22T20:42:23.857 回答
1

我在 IE 7/8 中遇到了同样的错误。在包括 IE 9/10 在内的所有其他浏览器中运行良好。

我发现对我有用的是消除自闭标签。

坏的:

<div>
    <span data-bind="text: name"/>
</div>

好的:

<div>
    <span data-bind="text: name"></span>
</div>
于 2015-03-07T17:43:36.230 回答
1

就我而言,我正在添加一个不存在的元素,或者,我正在向一个可能存在的元素添加绑定,但它的父元素没有。与此类似:

var segDiv =  $("#segments"); // did not exist, wrong id
var theDiv = segDiv.html("<div></div>");

ko.applyBindings(someVM, theDiv);

据我所知,这个错误似乎有点超载,因为它会触发元素可能发生的许多不同错误,比如它不存在。因此,错误描述可能具有高度欺骗性。它可能应该是这样的:

Failure to bind bindings to element. Possible reasons include: multiple binding attempts, element not existing, element not in DOM hierarchy, quirks in browsers, etc
于 2017-02-06T09:38:25.050 回答
0

我有同样的问题,我是这样解决的:

var vm = new MessagesViewModel()
ko.applyBindings(vm)

function ShowMessagesList() {
   vm.getData("MyParams")
}

setInterval(ShowMessagesList, 10000)
于 2014-04-17T11:12:18.947 回答
0
ko.cleanNode($("#modalPartialView")[0]);
ko.applyBindings(vm, $("#modalPartialView")[0]);

这对我有用,但正如其他人所说,这cleanNode是一个内部 ko函数,所以可能有更好的方法。

于 2018-08-27T09:33:53.083 回答