动态生成元素的淘汰数据绑定
Posted
技术标签:
【中文标题】动态生成元素的淘汰数据绑定【英文标题】:knockout data-bind on dynamically generated elements 【发布时间】:2012-06-19 11:19:01 【问题描述】:如何使剔除数据绑定对动态生成的元素起作用?例如,我在 div 中插入了一个简单的 html 选择菜单,并希望使用敲除选项绑定来填充选项。这是我的代码的样子:
$('#menu').html('<select name="list" data-bind="options: listItems"></select>');
但是这种方法不起作用。有什么想法吗?
【问题讨论】:
在你完成你的 ko.applyBindings(yourVMHere); 之后添加这个; 放弃对这个动态添加的 DOM 元素进行(自动)KO 绑定的想法并手动处理。 底部附近的正确答案:***.com/a/29903552/3093731 【参考方案1】:如果您在绑定视图模型后动态添加此元素,它将不在视图模型中并且不会更新。你可以做两件事之一。
-
将元素添加到 DOM 并通过再次调用
ko.applyBindings();
重新绑定它
或者从头开始将列表添加到 DOM,并将视图模型中的选项集合留空。在您稍后将元素添加到选项中之前,Knockout 不会呈现它。
【讨论】:
如果我再次调用 applyBindings 会抛出一个错误:错误:您不能将绑定多次应用于同一个元素。 这一定是最新框架的新特性。第二种选择仍然可行,老实说,这是一个更好的选择。 是的,我想这么多,在一个元素上应用绑定一次以上是不好的做法。因为它会触发 2 次,我认为这就是为什么他们在 KO 3 中添加了一些警告【参考方案2】:淘汰赛 3.3
ko.bindingHandlers.htmlWithBinding =
'init': function()
return 'controlsDescendantBindings': true ;
,
'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
element.innerHTML = valueAccessor();
ko.applyBindingsToDescendants(bindingContext, element);
;
上面的代码 sn-p 允许您使用“htmlWithBinding”属性动态注入 html 元素。然后还会评估添加的子元素...即它们的数据绑定属性。
【讨论】:
【参考方案3】:重写html绑定代码或创建一个新的。因为 html 绑定可以防止动态 html 中的“注入绑定”:
ko.bindingHandlers['html'] =
//'init': function()
// return 'controlsDescendantBindings': true ; // this line prevents parse "injected binding"
//,
'update': function (element, valueAccessor)
// setHtml will unwrap the value if needed
ko.utils.setHtml(element, valueAccessor());
;
【讨论】:
在查看了该线程上的所有答案和 cmets 之后,IMO 这实际上是“动态生成元素上的淘汰数据绑定”问题的最佳解决方案。很好的解决方案! 如果理解这一点的人可以将其编辑为更易于理解,我将不胜感激:)【参考方案4】:对于 v3.4.0,使用下面的自定义绑定:
ko.bindingHandlers['dynamicHtml'] =
'update': function (element, valueAccessor, allBindings, viewModel, bindingContext)
// setHtml will unwrap the value if needed
ko.utils.setHtml(element, valueAccessor());
ko.applyBindingsToDescendants(bindingContext, element);
;
【讨论】:
当我创建带有绑定的新标签时如何调用这个绑定?【参考方案5】:编辑:自LosManos指出的 IIRC 版本 2.3 以来,这似乎不起作用
您可以使用 myViewModel[newObservable] = ko.observable('') 将另一个 observable 添加到您的视图模型中
之后,再次调用 ko.applyBindings。
这是一个简单的页面,我在其中动态添加段落,新的视图模型和绑定完美无缺。
// myViewModel starts only with one observable
var myViewModel =
paragraph0: ko.observable('First')
;
var count = 0;
$(document).ready(function()
ko.applyBindings(myViewModel);
$('#add').click(function()
// Add a new paragraph and make the binding
addParagraph();
// Re-apply!
ko.applyBindings(myViewModel);
return false;
);
);
function addParagraph()
count++;
var newObservableName = 'paragraph' + count;
$('<p data-bind="text: ' + newObservableName + '"></p>').appendTo('#placeholder');
// Here is where the magic happens
myViewModel[newObservableName] = ko.observable('');
myViewModel[newObservableName](Math.random());
// You can also test it in the console typing
// myViewModel.paragraphXXX('a random text')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<div id="placeholder">
<p data-bind="text: paragraph0"></p>
</div>
<a id="add" href="#">Add paragraph</a>
【讨论】:
这似乎引发了相同的“无法应用绑定两次”错误。是否可以告诉 ko.applyBindings() 您要添加到绑定中的非常具体的元素? 此解决方案无法解决问题。通常,动态添加的元素将属于同一类型,这意味着它应该调用与绑定到 VM 相同的处理程序。例如:VM.loadData = f() handling.. 并希望将其数据绑定到任何(特定)div 上,并动态添加到 DOM 中。使用您的方法,新元素如何在单击时具有相同的功能? 检查这个小提琴:jsfiddle.net/rniemeyer/F7pLN 从 2.3 IIRC 版本开始,两次调用 applyBindings 是错误的。【参考方案6】:这是一个老问题,但这是我希望得到的最新答案(淘汰赛 3.3.0):
当使用 knockout 模板或自定义组件将元素添加到预绑定的 observable 集合时,knockout 将自动绑定所有内容。您的示例看起来像是一个可观察的菜单项集合,可以开箱即用。
【讨论】:
正确答案。只需将元素加载到可淘汰的可观察数组中,而不是直接添加到页面中。这就是淘汰赛的目的。或者,在将动态元素添加到页面之前不要绑定到它。【参考方案7】:基于this existing answer,我已经实现了与您最初的意图相似的东西:
function extendBinding(ko, container, viewModel)
ko.applyBindings(viewModel, container.children()[container.children().length - 1]);
function yourBindingFunction()
var container = $("#menu");
var inner = $("<select name='list' data-bind='options: listItems'></select>");
container.empty().append(inner);
extendBinding(ko, container,
listItems: ["item1", "item2", "item3"]
);
这里有一个JSFiddle 可以玩。
请注意,一旦新元素成为 dom 的一部分,就无法通过调用 ko.applyBindings
重新绑定它——这就是我使用 container.empty()
的原因。如果您需要保留新元素并使其随着视图模型的变化而变化,请将 observable 传递给 extendBinding
方法的 viewModel
参数。
【讨论】:
【参考方案8】:查看此答案:How do define a custom knockout 'options binding' with predefined Text and Value options
ko.applyBindingsToNode
特别有用。
【讨论】:
以上是关于动态生成元素的淘汰数据绑定的主要内容,如果未能解决你的问题,请参考以下文章
JQuery 动态加载 HTML 元素时绑定点击事件无效问题