Как отделить шаблон от компонентов трафарета (шаблон отложенной загрузки)
Интересная задача, поэтому читайте до конца. то, что я хочу достичь, - это разделить шаблон в другом файле 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», поэтому он проанализирует ваш проект, чтобы выяснить, какие функции вы на самом деле используете, и включит только их в окончательный пакет. Если вы проверите
Я создал собственное быстрое воспроизведение и сравнил этот файл при использовании динамического и статического импорта. Вот отличия:
Динамический импорт
{ 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>;
}
}