【问题标题】:KnockoutJS bindinghandler with childBindingContext - $data === $parentKnockoutJS bindinghandler with childBindingContext - $data === $parent
【发布时间】:2013-10-17 17:36:36
【问题描述】:

我目前正在编写一个自定义绑定处理程序以在我们的页面中形成一个控件。
该控件生成自己的视图模型,作为主视图模型的子视图,以不改变原始视图模型。 (控件的实现与页面无关)

代码示例
我创建了一个抽象示例:
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>

问题
绑定处理程序的视图模型上可用的 $data 实际上是父(主)视图模型。这似乎是一种奇怪的行为,因为其他属性(例如 subValue)实际上是正确绑定的。这些属性在主视图模型上不存在。

猜测
我的猜测是 controlsDescendantBindings 仅在绑定发生后返回。因此,主视图模型渗透。然后 KO 倾向于使用 mainviewmodel-context 中存在的 $data。

问题
(考虑到我的猜测是正确的)
是否有适当的方法来创建子视图模型并将其绑定到(在本例中为虚拟的)绑定处理程序自己的控件?

【问题讨论】:

    标签: knockout.js knockout-2.0


    【解决方案1】:

    唉,重大疏忽。

    我的实现基于文档页面:
    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 sn-p 变为:

    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>';
    

    【讨论】:

    • 四年过去了,这简直是一鸣惊人,解决了我的问题,谢谢 :) 想知道有多少人被该文档所困扰?
    猜你喜欢
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    • 2014-01-20
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    相关资源
    最近更新 更多