简体   繁体   English

使用单独的html和js文件创建一个vanilla js web组件

[英]creating a vanilla js web-component with separate html and js files

While creating vanilla JS web-components, I am trying to figure out a way to keep the template html outside the JS file, preferably in a separate HTML file. 在创建vanilla JS Web组件时,我试图找到一种方法将模板html保存在JS文件之外,最好是在单独的HTML文件中。

I did look into multiple implementations of native JS web-component implementations notably here , single file and a very nice writeup here . 我没有考虑本地JS网页组件实现的多种实现特别是在这里单个文件一个非常漂亮的书面记录在这里

All of the implementations end up putting the html template inside the JS using string literals or similar methods. 所有实现最终都使用字符串文字或类似方法将html模板放在JS中。 My question is, is it even possible to make two separate files, for example my-component.html for template and my-component.js for JS code? 我的问题是,是否可以制作两个单独的文件,例如my-component.html for template和my-component.js for JS code?

I have seen this approach working nicely in Aurelia framework, it is very clean and keeps the code where it belongs. 我已经看到这种方法在Aurelia框架中运行良好,它非常干净并且将代码保存在它所属的位置。

I tried using html imports, by creating a html file for template and including js inside it. 我尝试使用html导入,通过为模板创建一个html文件并在其中包含js。

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

that theoretically should work but html imports is already abandoned by browsers. 理论上应该可行,但浏览器已经放弃了html导入。

My second approach, that seems a bit hack to me, but it does work is to pull the template html from server in the connectedCallback 我的第二种方法,对我来说似乎有点破解,但它确实有效是从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);

from the server side I simply return pure html 从服务器端我只是返回纯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>

Notice how I have skipped the <template> tag altogether in the response coming from server, as obviously if I use <template> tag, I will have to use dom parsing to actually put the html into dom. 请注意我是如何在来自服务器的响应中完全跳过<template>标签的,因为很明显,如果我使用<template>标签,我将不得不使用dom解析来实际将html放入dom中。

This does work but it looks so hackish. 这确实有效,但它看起来如此hackish。

Does anyone has a better approach? 有没有人有更好的方法?

You solution is good but you could cut in the Javascript code: 你的解决方案很好,但你可以切入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 )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM