#knockout.js #knockout-templating
#knockout.js #выбивание шаблонов
Вопрос:
В настоящее время я разрабатываю механизм компоновки, используя knockout в качестве основы, но я столкнулся с небольшой проблемой. (извините за длинный пост)
Я использую выбивание 3.5.1.
У меня есть следующее index.html:
<body>
<toolbar-dock ui-name="toolbar"></toolbar-dock>
<general-layout ui-name="main" params="resize: true">
<!-- this one is transparent, and overlays ontop of the main screen. -->
<general-dock ui-name="ui" params="resize: 'fit'" id="hud_overlay"></general-dock>
</general-layout>
<main-statusbar></main-statusbar>
</body>
general-dock имеет следующий .html:
<horizontal-dock>
<vertical-dock ui-name="left"></vertical-dock>
<vertical-dock ui-name="middle">
<horizontal-dock ui-name="top"></horizontal-dock>
<content-dock ui-name="middle">
</content-dock>
<horizontal-dock ui-name="bottom"></horizontal-dock>
</vertical-dock>
<vertical-dock ui-name="right" ></vertical-dock>
</horizontal-dock>
Функция UIManager.registerDockType регистрирует dock с knockout со следующими параметрами:
- ComponentName: первый параметр — это имя пользовательского элемента, который используется для регистрации в knockout.
- DockClass: создается экземпляр второго параметра и передается элементу.
- TemplateString: третий параметр — это строка шаблона, предоставляемая классу knockout .
Фактически функция заключается в следующем:
ko.components.register(ComponentName, {
template: TemplateString,
viewModel: {
createViewModel: (params, componentInfo) => {
if (!componentInfo) {
throw new Error("Component didn't initialise correctly.");
}
var context = ko.contextFor(componentInfo.element);
new DockClass(componentInfo.element);
return context.$data;
}
}
})
И вызывается так:
UIManager.registerDockType("vertical-dock", VerticalDock, "<!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->");
UIManager.registerDockType("horizontal-dock", HorizontalDock, "<!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->");
UIManager.registerDockType("content-dock", CenterDock, "<!-- ko template: { nodes: $componentTemplateNodes } --><!-- /ko -->");
Я ожидал, что будет выведен следующий HTML:
<body>
<toolbar-dock ui-name="toolbar"></toolbar-dock>
<general-layout ui-name="main" params="resize: true">
<horizontal-dock>
<vertical-dock ui-name="left"></vertical-dock>
<vertical-dock ui-name="middle">
<horizontal-dock ui-name="top"></horizontal-dock>
<content-dock ui-name="middle">
<!-- There should be an error, blank entry or infinite duplication at this point because $componentTemplateNodes is now exhausted? -->
</content-dock>
<horizontal-dock ui-name="bottom"></horizontal-dock>
</vertical-dock>
<vertical-dock ui-name="right" ></vertical-dock>
</horizontal-dock>
</general-layout>
<main-statusbar></main-statusbar>
</body>
Но то, что я получаю, это:
<body>
<toolbar-dock ui-name="toolbar"></toolbar-dock>
<general-layout ui-name="main" params="resize: true">
<horizontal-dock>
<!-- ko template: { nodes: $componentTemplateNodes } -->
<!-- this one is transparent, and overlays ontop of the main screen. -->
<general-dock ui-name="ui" params="resize: 'fit'" id="hud_overlay"></general-dock>
<!-- /ko -->
</horizontal-dock>
</general-layout>
<main-statusbar></main-statusbar>
</body>
Почему это происходит? Почему внутри горизонтальной привязки я получаю $componentTemplateNodes общего макета?
Когда я использовал knockout 3.4.0 и выделял <!-- ko template
узел с помощью knockout-inspector, он показывал $componentTemplateNodes, которые я ожидал, однако в DOM на самом деле были родительские $ componentTemplateNodes. После обновления до версии 3.5.0 knockout-inspector и DOM показывают одно и то же (хотя и не то, что я ожидал).
Я ожидал, что (как и в случае с $data) новый $componentTemplateNodes создается каждый раз, когда вводится узел шаблона, контролируемый нокаутом, если у этого узла шаблона есть дочерние элементы. И что при рекурсии вниз по dom каждый дочерний элемент, удовлетворяющий этим критериям, заменит текущие $componentTemplateNodes на свои собственные $componentTemplateNodes.
Это означало бы, что $componentTemplateNodes для general-dock
будет:
<!-- this one is transparent, and overlays ontop of the main screen. -->
<general-dock ui-name="ui" params="resize: 'fit'" id="hud_overlay"></general-dock>
Но как только мы доберемся до horizontal-dock
того, когда knockout расширяет general-dock, он создаст новое значение $componentTemplateNodes (поскольку у него есть дочерние элементы), содержащее следующее представление:
<vertical-dock ui-name="left"></vertical-dock>
<vertical-dock ui-name="middle">
<horizontal-dock ui-name="top"></horizontal-dock>
<content-dock ui-name="middle">
</content-dock>
<horizontal-dock ui-name="bottom"></horizontal-dock>
</vertical-dock>
<vertical-dock ui-name="right" ></vertical-dock>
Я ожидал, что единственным способом вернуться к исходным $componentTemplateNodes будет либо повторное использование $parentContext, либо передача их в качестве параметра.
Это ошибка или я делаю что-то глупое?