我正在尝试使用knockout来创建一个html编辑器/预览器。我使用单个observable设置了一个简单的测试,如下所示:
JS:
var ViewModel = function() {
this.content = ko.observable("<div data-bind=\"text: 'testext'\"></div>");
};
ko.bindingHandlers.bindHTML = {
'init': function () {
},
'update': function (element, valueAccessor) {
ko.utils.setHtml(element, valueAccessor());
}
}
ko.applyBindings(new ViewModel());
HTML:
<input type="text" data-bind="value: content">
当页面首次加载时,这似乎工作正常,在其中显示带有'testext'的div,但是只要我将输入字段编辑为类似
<div data-bind=\"text: 'testext2'\"></div>
绑定不起作用!
这是淘汰赛的限制,还是我做错了什么?有没有办法预先形成重新绑定?
这里有一个JSFiddle:http://jsfiddle.net/Q9LAA/
答案 0 :(得分:4)
有一个html
绑定可以自动为你插入html(我更喜欢使用setHtml
),但它不会评估插入的html上的绑定,你必须重新应用生成的html上的绑定(这是你需要自定义绑定的地方)。
ko.bindingHandlers.bindHTML = {
init: function () {
// we will handle the bindings of any descendants
return { controlsDescendantBindings: true };
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
// must read the value so it will update on changes to the value
var value = ko.utils.unwrapObservable(valueAccessor());
// create the child html using the value
ko.applyBindingsToNode(element, { html: value });
// apply bindings on the created html
ko.applyBindingsToDescendants(bindingContext, element);
}
};
这是一个更新的fiddle,展示了它的用途。
答案 1 :(得分:1)
如果我理解正确,你想使用类似Knockout html
绑定的东西,但你尝试绑定的HTML包含绑定。问题是您的HTML已加载,但Knockout不会自动对更改的HTML执行applyBindings()
。
所以你想要的是:
ko.bindingHandlers.bindHTML = {
init: function () {
// Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
return { 'controlsDescendantBindings': true };
},
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
// setHtml will unwrap the value if needed
ko.utils.setHtml(element, valueAccessor());
var elementsToAdd = element.children;
for (var i = 0; i < elementsToAdd.length; i++) {
ko.cleanNode(elementsToAdd[i]); //Clean node from Knockout bindings
ko.applyBindings(bindingContext, elementsToAdd[i]);
}
}
};
我使用for
循环迭代你要追加的html元素的原因是因为假设你想使用bindHTML
绑定追加:
<input type="text" data-bind="value: 'watermelon'" />
<input type="text" data-bind="value: 'orange'" />
使用for
循环,每个input
元素都会被正确绑定。
这是您更新并正常工作的JSFiddle
注意:请勿执行我在下面显示的内容。
您可能会对具有ko.applyBindings()
绑定的元素执行bindHTML
,以自动绑定其所有子节点。 这是一个非常糟糕的主意!
如果你这样做,你将进入一个无限循环,因为你会要求knockout再次执行bindHTML,并再次执行。这是一个无限的递归循环!