Litelement - Table 排序呈现错误的值

Litelement - Table sorting renders wrong values

我正在尝试根据 Lit 元素中的值对 HTML table 进行排序。但是,我 运行 遇到了我的组件的问题。这是我的概述 table;

问题

在此应用程序中,您需要能够对每个 table header 进行排序。但是,被视为 'done' 的项目需要移至 table 的底部。每当我将项目标记为已完成时,我的问题就会出现。在下面的示例中,我会将最重要的待办事项(任务:123)标记为已完成。预期的行为是待办事项被移动到 table 的底部并启用了它的复选框。不过目前还不是这个结果。

如您所见,任务为 123 的待办事项已移至底部。但是,任务 456 的待办事项也标记了它的复选框。这不是我们想要的行为,我不知道是什么原因造成的。您还可以看到颜色不正确(这是一些样式,向您显示正在保存已更改的待办事项,黄色 = 保存,绿色 = 保存,红色 = 错误)。

我尝试过的东西

因为我不知道究竟是什么导致了这个问题,所以我不知道我应该做什么。我提供了我所有 inputs/rows/td 的 ID 以确保没有任何混淆,但这似乎不起作用。

代码

import { LitElement, html, css } from 'lit-element';

class TableList extends LitElement {
    static get properties() {
        return {
            data: {
                type: Array
            },
            primaryKey: {
                type: String
            },
            defaultSortKey: {
                type: String
            }
        };
    }

    set data(value) {
        let oldValue = this._data;
        this._data = [ ... value];
        this.sortByHeader();
        this.requestUpdate('data', oldValue);
    }

    get data() {
        return this._data;
    }
    
    async edit(entry, key, event) {
        this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('saved');
        this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('error');
        this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.add('saving');

        if (entry[key].type === "checkbox") {
            entry[key].value = event.target.checked;
        } else {
            entry[key].value = event.target.value;
        }

        if (await update(entry)) {
            this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('saving');
            this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.add('saved');

            setTimeout(() => {
                this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('saved');
            }, 1000);
        } else {
            this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('saving');
            this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.add('error');

            setTimeout(() => {
                this.shadowRoot.getElementById('entry' + entry[this.primaryKey].value).classList.remove('error');
            }, 5000);
        }
    }

    sortByHeader(key) {       
        if (key === undefined) {
            key = this.defaultSortKey;
        }

        let oldValue = this.data;
        this._data = [ ... this.data.sort((a, b) => {
            return a[this.defaultSortKey].value - b[this.defaultSortKey].value 
                        || a[key].value - b[key].value;
        })];

        this.requestUpdate('data', oldValue);
    }

    renderHeaders() {
        let keys = Object.keys(this.data[0]);

        return keys.map(key => html`
            ${this.data[0][key].visible ?
                html`
                    <th id="${'header' + key}" @click="${() => this.sortByHeader(key)}">
                        ${key}
                    </th>
                `: ''
            }
        `)
    }

    renderRows() {
        return this.data.map(entry => html`
        <tr id="${'entry' + entry[this.primaryKey].value}">
            ${Object.keys(entry).map(key => html`
                ${entry[key].visible && !entry[key].editable ?
                    html`<td>${entry[key].value}</td>`
                    : ``
                }
                ${entry[key].visible && entry[key].editable ?
                    html`<td id="${'td' + key + entry[this.primaryKey].value}">
                            <input
                                id="${'input' + key + entry[this.primaryKey].value}"
                                name="${'input' + key + entry[this.primaryKey].value}"
                                type="${entry[key].type}"
                                ?checked="${entry[key].value}"
                                value="${entry[key].value}"
                                @change="${(event) => {
                                    this.edit(entry, key, event)
                                }}"
                            />
                        </td>`
                    : ``
                }
            `)}
        </tr>
        `)
    }

    render() {
        return html`
            <table id="table-list">
                <thead>
                    <tr>
                        ${this.renderHeaders()}
                    </tr>
                </thead>
                <tbody>
                    ${this.renderRows()}
                </tbody>
            </table>
      `;
    }

    static get styles() {
        return css`
            table {
                width: 100%;
                border-collapse: collapse;
                font-family: Arial, Helvetica, sans-serif;
            }

            th {
                padding-top: 12px;
                padding-bottom: 12px;
                text-align: center;
                background-color: #4CAF50;
                color: white;
            }

            tr {
                text-align: right;
                -moz-transition: all .2s ease-in;
                -o-transition: all .2s ease-in;
                -webkit-transition: all .2s ease-in;
                transition: all .2s ease-in;
                background: white; 
                padding: 20px;
            }

            .disabled {
                color: lightgrey;
            }

            .saving {
                background: yellow;
            }

            .saved {
                background: lightgreen;
            }

            .error {
                background: red;
            }

            .sort:after {
                content: ' ↓';
            }
        `;
    }
}

export default TableList;
  1. 如果您在模板中使用带有 id 的数组,请使用 lit-html

    的重复函数

    从“lit-html/directives/repeat”导入{重复};

  2. 对于样式,请勿手动将 类 添加到 DOM。使用来自 lit-html

    的 classMap

    从“lit-html/directives/class-map”导入 {classMap};

我解决了您的复选框问题,请按照此操作link

有关 lit-html 的更多信息,请参阅他们的 documentation