KnockoutJS 绑定

Posted

技术标签:

【中文标题】KnockoutJS 绑定【英文标题】:KnockoutJS Binding 【发布时间】:2015-05-27 05:39:26 【问题描述】:

我有在 ajax 应用程序中创建的视图模型。 ko.applyBindings() 在我渲染我的第一段 html 时被调用。稍后我进行第二次 ajax 调用以呈现 html 的另一部分并绑定到同一个视图模型。但是,因为当我第一次调用 ko.applyBindings() 时,第二个 ajax 中的 html 元素不存在,所以当我的第二部分 html 被检索时,数据绑定不起作用。

这是一个非常简单的示例,其中第一个复选框正确绑定。然后 content2 将通过后续的 ajax 调用加载,并且复选框无法绑定

<div id='container'>
    <div id="content1"> <span>Opt In</span>
        <input data-val-required="field is required." id="cbOptIn" name="OptIn" type="checkbox" data-bind="checked: OptIn"/>
    </div>    
</div



var ViewModel = function () 
    var self = this;
    self.OptIn = ko.observable(false);
    self.OptIn2 = ko.observable(false);


var appVM = new ViewModel();
ko.applyBindings(appVM);

appVM.OptIn(true);

var content2 = document.createElement('div');
content2.id = 'content2';
content2.innerHTML = '<span>Opt In2</span><input data-val-required="field is required." id="cbOptIn2" name="OptIn2" type="checkbox" data-bind="checked: OptIn2"/>';
document.getElementById('container').appendChild(content2);

appVM.OptIn2(true);

我也尝试通过创建两个单独的视图模型来解决这个问题,但后来我得到了

"You cannot apply bindings multiple times to the same element."

【问题讨论】:

您不能多次应用applybindings ko 的工作原理。但是您可以尝试使用cleanNode 并在主div 上重新应用绑定应该可以正常工作。欢呼 如果 cleanNode 那么我将不得不重新填充整个模型? 确实是的,它在这里重新评估了小提琴jsfiddle.net/supercool/BrsmC/47。有一种更好的方法(并非总是如此),例如您可以在第一次 applybindings 和 hide it 以及在 ajax 成功 show it 的 div 中编写动态内容。欢呼 进行 Ajax 调用的 Web 服务是否返回 JSON 或 HTML?通常的 KO 方法是使用 self.optInList = ko.observableArray([OptIn, OptIn2]),然后通过 &lt;div id="content1" data-bind="foreach: optInList"&gt; 更新 DOM。然后,当您的 Ajax 调用获取新的 optIn 项时,您将它们推送到列表中,并且 DOM 更新、绑定等等。 我在返回 HTML 时遇到问题的 Ajax 调用。当我进行 Ajax 调用以更新先前呈现的 HTML 片段时,我已经在执行您所描述的操作了 【参考方案1】:

我假设您的精简版本在功能上与您的实际情况不同,并且您正在使用 jQuery load() 调用来引入片段。如果是这种情况,您可以使用几个函数用于重新应用绑定:ko.dataFor()ko.cleanNode()ko.applyBindings()

如果您将片段加载到元素中:

element.load('path/to/fragment.html', function() 
  // do stuff
);

并且该元素或其他一些父元素已绑定到视图模型,您可以使用如下函数重新应用绑定:

var reapplyBindings = function(element) 
  // grab the viewmodel that has been applied to this element
  var viewModel = ko.dataFor(element);

  // if the viewmodel exists, clean the node and re-apply the viewmodel
  // to the element (and all of it's children)
  if(viewModel) 
    ko.cleanNode(element);
    ko.applyBindings(vm, element);
  

现在,使用这个功能:

element.load('path/to/fragment.html', function() 
  reapplyBindings(element);
  // do stuff you were doing before
);

这是可行的,因为即使您可能没有将视图模型显式应用到正在加载的元素,敲除仍然可以从 DOM 更远的位置获取视图模型。

这种方法唯一真正需要注意的是cleanNode 函数;它将删除所有事件处理程序,因此需要重新应用它们(除非您将它们附加到父元素,在这种情况下您很好)。

【讨论】:

我不想重新应用所有的事件处理程序。我发现也有效的是来自下面的链接,在那里我可以告诉 KO 停止绑定某个部分,然后再次调用 ApplyBindings() 但传入一个不同的元素,该元素不是我 applyBindings 到的另一个元素的子元素。然后我不必重新应用任何处理程序或绑定。 knockmeout.net/2012/05/quick-tip-skip-binding.html

以上是关于KnockoutJS 绑定的主要内容,如果未能解决你的问题,请参考以下文章

knockoutjs:值绑定独占还是点击事件?

knockoutjs 引发无法解析绑定属性

如何调试 KnockoutJS 的模板绑定错误?

KnockoutJS:设置 optionValue 打破“与”绑定

KnockoutJS 绑定

Knockoutjs 单页应用程序绑定问题