Как отделить шаблон от компонентов трафарета (шаблон отложенной загрузки)

Интересная задача, поэтому читайте до конца. то, что я хочу достичь, - это разделить шаблон в другом файле js и при необходимости отложить его загрузку. То же, что и в экосистеме React, работает, а трафарет - нет! Репозиторий сортировки https://github.com/pranav-js/triage-repo

У меня есть шаблон tsx в другом файле .js, например

template-three.js имеет простой onClick, который только предупреждает

      import { h } from '@stencil/core';
export const template_three = () => {
  return <button onClick={() => alert()}>Template three here</button>;
};

когда я пытаюсь вызвать этот метод, импортировав в component-two.tsx вот так

      import { Component, Fragment, h, Host, State } from '@stencil/core';

@Component({
  tag: 'component-two',
  styleUrl: 'component-two.css',
  shadow: true,
})
export class ComponentTwo {
  @State() showComponentOne: any;
  method: any;
  template: string = '';

  constructor() {}

  componentWillRender() {
    this.fetchComp(2);
  }

// lazy load template when needed based on type passed

  fetchComp(type) {
    let this_ = this;
    switch (type) {
      case 0:
        import('./template').then(module => {
          this.showComponentOne = module.template_one;
        });
        break;
      case 1:
        import('./template-two').then(module => {
          this.showComponentOne = module.template_two;
        });
        break;
      case 2:
          import('./template-three').then(module => {
            this.showComponentOne = module.template_three;
          );
        break;
      default:
        break;
    }
  }

  clicked() {
    alert();
  }

  methodHere() {}

// check if template received then simply call that method with this attached

  render() {
    let this_ = this;
    return this.showComponentOne ? this.showComponentOne.apply(this) : <div></div>;
  }
}

Просматривайте отрисовки , но списки событий не работают : /, даже не простое предупреждение :(. Когда я проверяю, я не вижу никакого события, прикрепленного к кнопке. Однако, если та же функция, которую я сохраняю внутри класса компонента, она работает :(! !!

проверьте два разных объекта, когда шаблон определен внутри и снаружи компонента.

Можете ли вы сказать мне, что я здесь делаю не так?

Я не могу хранить шаблоны в компоненте только потому, что у меня много пользовательских интерфейсов для той же логики. До сих пор у меня не было возможности в Интернете, этот ответ не помогает ни Передача настраиваемого шаблона в компонент трафарета

2 ответа

Я думаю, что проблема заключается в сочетании API-интерфейса Stencil с поддержкой дерева и проблемы с его анализом динамического импорта во время сборки.

Stencil старается поставлять как можно меньше кода «Stencil», поэтому он проанализирует ваш проект, чтобы выяснить, какие функции вы на самом деле используете, и включит только их в окончательный пакет. Если вы проверите (в сборке dev www) в строке 2 вы найдете список обнаруженных функций.

Я создал собственное быстрое воспроизведение и сравнил этот файл при использовании динамического и статического импорта. Вот отличия:

Динамический импорт

      { vdomAttribute: false, vdomListener: false }

Статический импорт

      { vdomAttribute: true, vdomListener: true }

Таким образом, кажется, что Stencil не знает о функциях, которые вы используете только в динамически импортированном шаблоне, и поэтому не включает их в сборку. Но если вы используете одни и те же функции в каком-либо компоненте (или в файле, который статически импортирован в компонент), Stencil должен включить их.

Таким образом, простым обходным решением будет присоединение любого слушателя к любому элементу в любом компоненте вашего проекта. И вам придется сделать это для каждой отдельной функции Stencil, которую вы в настоящее время используете только в динамически загружаемом шаблоне.

Другой вариант — создать компонент Stencil, который статически включает все ваши динамические шаблоны. Насколько я знаю, это обнаружит все используемые функции и активирует их для проекта, даже без необходимости использовать этот новый компонент где-либо.

Пример:

      import { Component, Host, h } from '@stencil/core';
import { Template1 } from "../../templates/template1";
import { Template2 } from "../../templates/template2";
import { Template3 } from "../../templates/template3";

@Component({
  tag: 'template-imports',
})
export class TemplateImports {
  render() {
    return (
      <Host>
        <Template1></Template1>
        <Template2></Template2>
        <Template3></Template3>
      </Host>
    );
  }
}

Я думаю, это должно быть

      @Component({
  tag: 'component-two',
  styleUrl: 'component-two.css',
  shadow: true,
})
export class ComponentTwo {
  // omitting all code that didn't change ...

  render() {
    // probably not needed
    let this_ = this;

    /* ---------------------------------------------------- */
    /* Note the change in the following line:               */
    /* showComponentOne must be the template function here. */
    /* ---------------------------------------------------- */
    return this.showComponentOne ? <this.showComponentOne onclick={this.onClick.bind(this)} /> : <div></div>;
  }
}
Другие вопросы по тегам