Knockoutjs;带有内部标记的自定义组件,引用调用者$ data及其$ parent

时间:2016-10-20 16:41:59

标签: knockout.js

我试图创建一个自定义组件,它有一些应该引用调用者bindingContext的内部标记,因为内部标记引用了调用者$ data和$ parent, 对于$ data,由于模板绑定上的数据选项没有问题,但是它的$ parent呢?

我找到了一个改变ko.bindingContext.prototype [' createChildContext']功能的糟糕解决方案 以这种方式设置自己[" $ parent"]:

self['$parent'] = parentContext['$parent'] === self["$data"] ? parentContext['$parents'][1]:parentContext['$data'];

不知道如何处理自己[' $ parents']:/ 你怎么看待这件事 ? 有干净的方法吗?

提前谢谢 kolja ** jsfiddle示例:https://jsfiddle.net/koljagava/nyh565xp

2 个答案:

答案 0 :(得分:0)

I think you want $parentContext (discussed here).

The node within the child template becomes

<div data-bind="text:variable1 + ' ' + $parentContext.$parents[1].someVariable()">

ko.components.register("parent-component", {
  viewModel: function(params) {
    this.params = params;
    this.someVariable = params.variable;
    this.innerContext = {
      variable1: "variable1",
      logIt: (f) => {
        console.log(f);
      }
    }
  },
  template: "<!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->"
});

ko.components.register("child-component", {
  viewModel: function(params) {
    this.params = params;
  },
  template: "<!-- ko template: { nodes: $componentTemplateNodes, data:$parent} --><!-- /ko -->"
});

ko.applyBindings({
  someVariable: ko.observable('someVariableWhoseValueIsHere')
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<parent-component params="variable: someVariable">
  <div data-bind="with:innerContext">
    <child-component>
      <div data-bind="text:variable1 + ' ' + $parentContext.$parents[1].someVariable()">
    </child-component>
    </div>
</parent-component>

答案 1 :(得分:0)

我找到了一个解决方案:使用ko customBinding

    ko.bindingHandlers.withCorrectBinding = {
        init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
            var idx = bindingContext.$parents.indexOf(valueAccessor());
            //if databinding is not in parents lets ko do normal binding 
            if (idx === -1)
              return;

            var childBindingContext = bindingContext.createChildContext(
                valueAccessor);
            childBindingContext.$parent = null;
            childBindingContext.$parents = [];
            if (idx+1<bindingContext.$parents.length){
              //$parent
              childBindingContext.$parent = bindingContext.$parents[idx+1];
              //$parents
              childBindingContext.$parents = bindingContext.$parents.splice(0,idx);
              //$rawData ???
              //$parentContext ???
            }

            ko.applyBindingsToDescendants(childBindingContext, element);

            // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice
            return { controlsDescendantBindings: true };
        }
    };

    ko.applyBindings({
    	var1: "var1Value",
      innerContext:{
      			var2 : "var2Value",
            innerInnerContext : {
            	var3 : "var2Value"
            }
      	}
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<div data-bind="with:innerContext">
  <div data-bind="with:innerInnerContext">
    <hr/>
    <div data-bind="with:$parent">
      Does not work<br>
      var2 : <div data-bind="text:var2"></div>
      var1 : <div data-bind="text:$parent.var1||'not found!'"></div>
    </div>
    <hr/>
    <div data-bind="withCorrectBinding:$parent">
      It works!<br>
      var2 : <div data-bind="text:var2"></div>
      var1 : <div data-bind="text:$parent.var1"||'not found!'></div>
    </div>
  </div>
</div>