#knockout.js
#knockout.js
Вопрос:
Я пытаюсь создать пользовательский компонент, имеющий некоторую внутреннюю разметку, которая должна ссылаться на вызывающий объект BindingContext, поскольку внутренняя разметка ссылается на вызывающий объект $ data и $ parent, для $ data нет проблем из-за опции data при привязке шаблона, но как насчет его $ parent?
Я нашел дерьмовое решение, изменив функцию ko.BindingContext.prototype[‘createChildContext’], устанавливающую self [«$ parent»] таким образом :
self['$parent'] = parentContext['$parent'] === self["$data"] ? parentContext['$parents'][1]:parentContext['$data'];
понятия не имею, как обращаться с self[‘$ parents’] :/ что вы об этом думаете? есть ли чистый способ сделать это?
заранее благодарю колю ** пример jsfiddle :https://jsfiddle.net/koljagava/nyh565xp
Комментарии:
1. В вашей модели, которая представлена как $ data, можете ли вы добавить ссылку на ее $ parent? Затем вы бы сделали что-то вроде $data.parent.someObservable …
2. Да, каким-то хитрым способом это возможно. Я ищу чистую реализацию. Если это возможно
3. Я часто использовал этот метод в knockout viewmodels — но я еще не использовал компоненты, поэтому я не знаю, как вы могли бы изменить свой дизайн, чтобы передать ссылку на родительский объект при инициализации модели вашего дочернего компонента.
Ответ №1:
Я думаю, вы хотите $parentContext
(обсуждалось здесь).
Узел в дочернем шаблоне становится
<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>
Ответ №2:
Я нашел решение: используя 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>