Порядок инициализации компонентов в polymer 2

#polymer #web-component #polymer-2.x #polymer-3.x

#полимер #веб-компонент #polymer-2.x #polymer-3.x

Вопрос:

Мы переносим приложение среднего размера с polymer 1 на polymer 3. Пока что мы застряли на промежуточном этапе по запуску наших гибридных компонентов в работу.

Мы сталкиваемся с некоторыми трудностями, касающимися времени инициализации компонентов. Например:

 <my-app>
  <my-component slot='componentslot'><my-component>
</my-app>
  

Кажется, есть случаи, когда my-component инициализируется перед my-app инициализацией. Он может варьироваться, является ли my-component частью shadow- или light-dom.

У нас есть много тесно связанных компонентов, которые зависят от детерминированного порядка инициализации. Например, существует древовидная структура, в которой каждое ребро и каждый лист используют события, чтобы обнаружить свою собственную глубину в дереве. Поэтому нам нужно, чтобы элементы верхнего уровня были инициализированы перед внутренними компонентами.

Но то, что мы обнаружили до сих пор, было по существу: нет гарантии для любого порядка инициализации компонентов.

Существует ли установленный шаблон для решения этой проблемы? Будет ли эта проблема решена в polymer 3 (так что нам все равно не нужно об этом заботиться)?

Редактировать

Меня попросили привести несколько более конкретных примеров

Пример 1

 <my-layout>
  <my-complex-component id="1">
    <my-reuseable-part/>
  </my-complex-component>
  <my-complex-component id="2">
    <my-reuseable-part/>
  </my-complex-component>
  <some-other-component>
    <my-reuseable-part/>
  </some-other-component>
</my-layout>
  

У меня есть несколько повторно используемых компонентов, которым нужно знать, находятся ли они внутри my-complex-component или some-other-component . my-complex-component использует context-discovery-behavior , который запускает событие, содержащее обратный вызов в качестве полезной нагрузки. my-complex-component и some-other-component имеют context-behavior устройства, которые прослушивают это событие и отвечают на него, вызывая обратный вызов.

Но, поскольку my-reusable-part это могло быть прикреплено до того, как my-complex-component или some-other-component прикреплено, этот шаблон не работает.

Регистрация прослушивателей событий, а также запуск события отключения выполняются в attached (т.е. connectedCallback ).

Пример 2

 <my-tree>
  <my-tree-edge>
    <my-tree-edge>
      <my-leaf/>
      <my-tree-edge>
        <my-leaf/>
      </my-tree-edge>
    </my-tree-edge>
    <my-tree-edge>
      <my-leaf/>
    </my-tree-edge>
    <my-leaf/>
  </my-tree-edge>
</my-tree>
  

В приведенном выше примере каждый лист и ребро должны знать, насколько глубоко они вложены. Снова каждый элемент запускает событие, и его родительский элемент ответит на событие. Снова регистрация прослушивателя и запуск события выполняются в attached / connectedCallback . И снова сбой механизма, если внутренний узел подключен до того, как будут подключены его родительские узлы.

Надеюсь, это поможет.

Комментарии:

1. Используете ли вы метод onReady?

Ответ №1:

Вы можете использовать dom-if element, если вы строго хотите быть уверены, что сначала выполните рендеринг, my-app затем вы можете разрешить рендеринг my-component чего-то вроде:

 <my-app ready="{{myAppReady}}>
  <template is='dom-if' if="[[myAppReady]]">
    <my-component slot='componentslot'><my-component>
  </template>
</my-app>
  

в скрипте my-app:

 static get properties(){return {
      ready:{type:Boolean,
             notify:true,
             value:false 
}}
  

в этой части вы можете добавить computed:"checkThisValuesToBeSUre(x,[y]..) , чтобы быть уверенным, зависит ли от некоторых значений, или вы можете добавить различные условия для отображения my-component

Кроме того, вы можете импортировать my-component.js динамически, например:

В my-app родительском скрипте:

 static get observers(){return ['_checkMyAppReady(myAppReady)']}

_checkMyAppReady(r){
   if(r) import('./my-component.js');
}
  

Редактировать

Если во многих элементах возникает одна и та же проблема, тогда лучше использовать lazy-import.js :

 _checkMyAppReady(r){
   if(r) import('./lazy-import.js');
}
  

lazy-import.js

 import './my-component.js';
import './my-component2.js';
import './my-component3.js';
...
  

Комментарии:

1. Перенос почти каждого элемента в dom-if действительно кажется неудобным обходным путем.

2. @samjaf На самом деле, немного подумав, вместо того, чтобы оборачивать каждый элемент. динамический импорт. Я имею в виду, что вы можете импортировать весь второй уровень (здесь my-component.js ) в lazy-import.js файл. Если вам нужен конкретный пример, я отредактирую свой ответ.

3. Спасибо за ваше обновление. Решение с использованием отложенного импорта было бы действительно лучше. К сожалению, это не сработает в ситуации, когда компоненты одного и того же типа вложены.

4. @samjaf В чем именно заключается проблема, поэтому вместо последовательной загрузки модуля может быть другое решение. Я имею в виду, что если вы не хотите активировать один скрипт, если некоторые данные не будут поступать из других элементов, то для этого есть несколько решений. Итак, пожалуйста, попробуйте добавить более конкретную проблему, которая у вас есть.