При создании ванильных веб-компонентов JS я пытаюсь найти способ сохранить шаблон HTML вне файла JS, предпочтительно в отдельном HTML-файле.
Я изучил несколько реализаций нативногоРеализации веб-компонентов JS, в частности, здесь , отдельный файл и очень хорошая запись здесь .
Все реализации заканчивают тем, что помещают htmlШаблон внутри JS, используя строковые литералы или аналогичные методы.У меня вопрос, возможно ли вообще сделать два отдельных файла, например my-component.html
для шаблона и my-component.js
для кода JS?
Я видел, как этот подход хорошо работает в среде Aurelia, он очень чистыйи хранит код там, где он принадлежит.
Я попытался использовать импорт html, создав html-файл для шаблона и включив в него js.
<link rel="import" href="my-component.html">
, который теоретически должен работать, но импорт html уже отменен браузерами.
Мой второй подход, который мне кажется немного хакерским, но он работает, это получить шаблон HTML с сервера в connectedCallback
// my-component.js
class MyComponent extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.initShadowDom();
}
async initShadowDom() {
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = await this.template;
}
async fetchData() {
return await fetch('my-template-url')
.then(function(response) {
return response.text();
});
}
get template() {
return (async () => {
return await this.fetchData();
})();
}
}
customElements.define('my-component', MyComponent);
со стороны сервера. Я просто возвращаю чистый HTML
// my-component.html
<style>
@import 'https://fonts.googleapis.com/icon?family=Material+Icons';
@import 'https://code.getmdl.io/1.3.0/material.${this.theme}.min.css';
@import 'http://fonts.googleapis.com/css?family=Roboto:300,400,500,700';
@import 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'
}
table {
border-collapse: collapse;
}
td {
text-align: center;
border: 1px solid #f7f7f7;
padding: 1rem;
}
th {
background-color: #f7f7f7;
text-align: center;
padding: 1em;
border: 1px solid #e9e9e9;
}
</style>
<div class="search-list table-responsive">
<table width="100%" class="table table-bordered table-striped table-hover">
<thead class="thead-light">
<tr>
<th width="1rem">
<input type="checkbox">
</th>
<th>
ID
</th>
<th>
name
</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox"></td>
<td>
1
</td>
<td>
some name
</td>
</tr>
</tbody>
</table>
</div>
Обратите внимание, как я вообще пропустил тег <template>
в ответе от сервера, так как, очевидно, если я использую тег <template>
, мне придется использовать синтаксический анализ dom, чтобы фактически поместить html вdom.
Это работает, но выглядит так глупо.
У кого-нибудь есть лучший подход?