Выбивание вложенных $componentTemplateNodes, возвращающих узлы неправильного контекста?

#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, либо передача их в качестве параметра.

Это ошибка или я делаю что-то глупое?