【问题标题】:Creating reusable web components for a single page in Vanilla JS?在 Vanilla JS 中为单个页面创建可重用的 Web 组件?
【发布时间】:2020-02-29 21:21:40
【问题描述】:

我有一个 HTML 页面,它使用 jQuery 创建一个表格来获取我的数据,并使用 vanilla JavaScript 来创建表格。我想为我的设置表创建方法创建一个类,以便我可以导出它并在整个 HTML 代码中重用它。我在正确的轨道上吗?

当前建表代码

function(data) {
                //Rename the variable so I can reuse some code 
                var data_list = data.dataList;
                //Headers for our tables second row
                var titles = data.headers;
                //HTML table variables
                var perRow = 2, html = "<table><tr>";
                //Loop through our array of data
                for (var i = 0; i < data_list.length; i++) {
                    //Add our header first, as we want that to appear first
                    html += "<td>" + titles[i]+ "</td>";
                    //Then add the correct data piece for the header
                    html += "<td>" + data_list[i]+ "</td>";
                    //Break into the next row
                    var next = i+1;
                    if (next % perRow == 0 && next != data_list.length) {
                        //Start new row
                        html += "</tr><tr>";
                    }
                }
                //End the table
                html += "</tr><table>";
                //Attach the table to the HTML doc when finished
                document.getElementById("container").innerHTML = html;
            };

我认为它在另一个 .js 文件中的样子

class dataTable extends HTMLElement {
    constructor() {
        super();

        //Get our data
        this.dataList = data.dataList;
        this.dataHeaders = data.headers;

        //HTML attribute for creating our table
        this.html = "<table><tr>";
    }

    createTable() {
        //Items we want per roq
        var perRow = 2;

        //Loop through our data
        for (var i = 0; i < this.dataList; i++) {
            //Add our headers first
            this.html += "<td>" + this.dataHeaders[i] + "</td>";
            //Then add the corresponding piece of data
            this.html += "<td>" + this.dataList[i] + "</td>";
            //Decide when to break into the next row
            var next = i+1;

            if (next % perRow == 0 && next != this.dataList.length) {
                //Add the end row HTML
                this. html += "</tr><tr>"
            }
        }
        //End the table
        this.html += "</tr><table>";

        document.getElementById("container").innerHTML = this.html;
    }
}

我在正确的轨道上吗?我应该只使用一个函数吗?如果我将它的 .js 文件包含在同一个目录中,这个类会正常工作吗?我只是想在学习框架之前使用一些 OOP 原理来制作自己的 Web 组件。

【问题讨论】:

  • 你在正确的轨道上。但据我所知,classextends 不是 Vanilla Javascript 的一部分,大多数浏览器都不支持它。您必须使用 classextends 创建 javascript,然后使用 webpack 编译它以将其转换为 vanilla javascript。
  • @KaleshKaladharan 是的,我观看的视频没有使用导出,他们只是将其保存为单独的 .js 文件并导入。谢谢
  • 可能他们转译了 ES6 js 文件并导入了生成的纯 javascript 文件。
  • class is certainly part of vanilla JavaScriptextends 也是如此。扩展HTMLElement 是一个不同的主题:Web Components,它们是一组标准,并非所有这些都得到广泛支持。
  • 注明。谢谢@HereticMonkey。你知道我在哪里可以了解如何扩展它吗?

标签: javascript jquery oop html-table web-component


【解决方案1】:

理想情况下,应该有一个 shadowRoot 并带有一个用于元素 html 的插槽,否则可以将表格插入到 shadowRoot 中。此示例将通过插槽定位 HTML:

在 HTML(静态页面或其他)中包括:&lt;data-grid&gt;data-grid&lt;/data-grid&gt;

在加载的模块中,通过导入或脚本 type=module:

/*
this is an example to show basics, it's not ideal, however it answers the question with a working example
*/
class DataTable extends HTMLElement {
    constructor() {
        super();
        // static, or request, or setup default and update later...
        this.dataList = [[1,2], [7,9]];
        this.dataHeaders = ['one', 'two'];

        // only work with shadowRoot in constructor, never the HTML element
        // minimize work here too, do that later in lifecycle callbacks
        this.attachShadow({mode:'open'}).innerHTML = `
<!-- NOTE how this th styling doesn't work because the table is rendered into the HTML, not the shadowRoot -->
<style>
/* styles shadow content in the host */
:host th{text-align:left;color:blue;}
/* only top-level selectors */
::slotted(table){text-align:right;}
</style>
<table style="width:100%;"><tr><th>ok</th></tr></table>
<button>update table</button>
<slot></slot>
        `;
        this.shadowRoot.querySelector('button').addEventListener('click', this.updateTable.bind(this));
    }
    connectedCallback(){
    // change attributes, html, etc here
        this.createTable();
    }
    random(){
        const max=Date.now();
        return Math.floor(Math.random() * Math.floor(max));
    }
    updateTable(){
        this.dataList = this.dataList.map((row, i)=>{
            return row.map(this.random);
        });
        this.createTable();
    }
    createTable() {
        // use the render cycle
        cancelAnimationFrame(this._createTable);
        this._createTable = requestAnimationFrame(()=>{
        // html will go into the shadowRoot slot (default or whatever is targeted)
        this.innerHTML = `
<table>
<thead><tr>
    ${ this.dataHeaders.reduce((html, col, i)=>{
        return html + `<th>${i+1} ${col}</th>`;
    }, '') }
</tr></thead>
<tbody>
<tr>${ this.dataList.map((row, i)=>{
    return `<td>${ row.join('</td><td>') }</td>`;
}).join('</tr><tr>') }</tr>
</tbody>
</table>
        `;
        });
    }
}
// define the element, if not already
customElements.get('data-grid') || customElements.define('data-grid', DataTable);

查看有效的example (commit) 和Web Components best-practices 的 Google Web Developer 文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-28
    • 2019-07-19
    • 2021-12-09
    相关资源
    最近更新 更多