【问题标题】:creating a vanilla js web-component with separate html and js files使用单独的 html 和 js 文件创建一个 vanilla js web 组件
【发布时间】:2019-04-08 09:58:23
【问题描述】:

在创建 vanilla JS web-components 时,我试图找出一种方法将模板 html 保留在 JS 文件之外,最好是在单独的 HTML 文件中。

我确实研究了原生 JS Web 组件实现的多个实现,特别是 heresingle filea very nice writeup here

所有实现最终都使用字符串文字或类似方法将 html 模板放入 JS 中。我的问题是,是否可以制作两个单独的文件,例如 my-component.html 用于模板,my-component.js 用于 JS 代码?

我已经看到这种方法在 Aurelia 框架中运行良好,它非常干净并且将代码保留在它所属的位置。

我尝试使用 html 导入,通过为模板创建一个 html 文件并在其中包含 js。

<link rel="import" href="my-component.html">

理论上应该可以,但是浏览器已经放弃了 html 导入。

我的第二种方法,这对我来说似乎有点骇人听闻,但它确实有效的是 从connectedCallback中的服务器拉取模板html

// 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>

注意我在来自服务器的响应中完全跳过了&lt;template&gt; 标签,显然如果我使用&lt;template&gt; 标签,我将不得不使用 dom 解析来实际将 html 放入 dom。

这确实有效,但看起来很老套。

有人有更好的方法吗?

【问题讨论】:

  • 这是我编写的一个工具,它使用 Rollup 将您的 HTML 和 Locale 文件转换为您的代码可以导入的内容,然后将其打包到每个组件的单个文件中:npmjs.com/package/component-build-tools

标签: javascript html web-component native-web-component


【解决方案1】:

您的解决方案很好,但您可以删减 Javascript 代码:

class MyComponent extends HTMLElement {

    async connectedCallback() {
        let res = await fetch( 'my-component.html' )

        this.attachShadow( { mode: 'open' } )
            .innerHTML = await res.text()
    }

}
customElements.define( 'my-component', MyComponent )

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2020-02-29
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 2014-09-21
  • 1970-01-01
相关资源
最近更新 更多