我目前正在编写一个自定义绑定处理程序,以在我们的页面中形成一个控件 此控件生成自己的viewmodel,也是主视图模型的子视图,以便不更改原始视图模型。 (控件的实现不是页面的关注点)
代码示例
我创造了一个抽象的例子:
http://jsfiddle.net/jdarn/
JS:
ko.bindingHandlers.subBinding = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var actualValue = valueAccessor();
ko.virtualElements.emptyNode(element);
var subViewModel = {};
subViewModel.subValue =
new ko.observable(ko.utils.unwrapObservable(actualValue) * 2);
var childBindingContext = bindingContext.createChildContext(viewModel);
ko.utils.extend(childBindingContext, subViewModel);
var getDomNodesFromHtml = function(html) {
var div = document.createElement('div');
div.innerHTML = html;
var elements = div.childNodes;
var arr = [];
for(var i = 0; i < elements.length; i++) {
arr.push(elements[i]);
}
return arr;
};
var html = '<p data-bind="text: subValue"></p>' +
'<pre data-bind="text: JSON.stringify(ko.toJS($data), null, 4)"></pre>';
ko.virtualElements.setDomNodeChildren(element, getDomNodesFromHtml(html));
ko.applyBindingsToDescendants(childBindingContext, element);
return { controlsDescendantBindings: true };
},
update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
}
};
ko.virtualElements.allowedBindings.subBinding = true;
var mainViewModel = {
value1: new ko.observable(100),
value2: new ko.observable(200)
};
ko.applyBindings(mainViewModel, document.getElementById('main'));
HTML:
<div id="main">
<p>Main viewmodel:</p>
<pre data-bind="text: JSON.stringify(ko.toJS($data), null, 4)"></pre>
<hr />
<!-- ko subBinding: value2 -->
<!-- /ko -->
</div>
问题
绑定处理程序的viewmodel上可用的 $ data 实际上是父(主)视图模型。这似乎是奇怪的行为,因为 subValue 等其他属性实际上是正确绑定的。主视图模型中不存在这些属性。
臆测
我的猜测是只有在绑定发生后才会返回controlsDescendantBindings。因此,主视图模型渗透。然后,KO支持主视图模式上下文中出现的$ data。
问题
(考虑到我的猜测是正确的)
是否有正确的方法来创建子视图模型并将其绑定到(虚拟的,在本例中为)绑定处理程序自己的控件?
答案 0 :(得分:4)
叹息,主要疏忽。
我的实施基于以下文档页面:
http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html
更新后的代码可在以下网址找到:
http://jsfiddle.net/jdarn/2/
<强>的变化:强>
var childBindingContext = bindingContext.createChildContext(viewModel);
ko.utils.extend(childBindingContext, subViewModel);
变为
var childBindingContext = bindingContext.createChildContext(subViewModel);
我误解了createChildContext接受的参数 - 此参数是子项上下文中的viewModel。
-
HTML控件片段变为:
var html = '<p data-bind="text: subValue"></p>' +
'data: <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 4)"></pre>' +
'parent: <pre data-bind="text: JSON.stringify(ko.toJS($parent), null, 4)"></pre>' +
'root through parentcontext: <pre data-bind="text: JSON.stringify(ko.toJS($parentContext.$root), null, 4)"></pre>' +
'root (not working): <pre data-bind="text: JSON.stringify(ko.toJS($root), null, 4)></pre>';