如何在自定义元素中创建自定义表?

时间:2018-10-31 12:42:36

标签: html css polymer custom-element lit-element

我正在处理具有 lit-element 的自定义元素。我想制作自己的自定义表格元素,但是有一些问题。

首先。似乎浏览器仅允许tr使用tdtable标签。

<!-- in html -->
<my-table>
  <tr>
    <td>A</td>
    <td>B</td>
  </tr>
</my-table>

<!-- chrome rendered -->
<my-table> A B </my-table>

第二。可以用CSS来模仿,但是CSS不能实现colspan。

<my-table> <!-- display: table -->
  <my-tr> <!-- display: table-row -->
    <my-td>A</my-td> <!-- display: table-cell -->
    <my-td colspan="3">B</my-td> <!-- There is no way to implement colspan -->
  </my-tr>
</my-table>

第三。我尝试在主机上使用“显示:内容”设置样式。似乎可行,但是主机没有像clientHeight这样的框大小数据。

class MyTd extends LitElement {
  render() {
    return html`
      <style>
        :host { display: content; }
        td {
          all: inherit; /* It make to inherit host's style */
          display: table-cell;
        }
      </style>
      <td>
        ${html`<slot></slot>`} // I don't know why it work.
      </td>
    `;
  }
}

// other js file.
const td = document.querySelector('my-td');
td.clientHeight; // 0

我可以覆盖clientHeight和其他内容(offsetHeightgetBoundingClientRect ...),但我不知道这是正确的,而且这是唯一的方法。

还有其他创建自定义表的方法吗,或者我的想法有问题吗?

1 个答案:

答案 0 :(得分:0)

这对于自定义元素来说并不是一个很好的用例 - 问题是当 room_id 存在并且在任何地方都可以使用时,为什么我要使用 <my-td>

可以在 CSS 中使用 <td> 来模仿表格,但您有更严重的问题 - 浏览器(和相关的 a11y 工具)将 column-count 的 DOM 视为结构化的数据表,而您的 <table> 只是另一个自定义元素。

这也打破了表格的 DOM 层次结构 - 即使您的元素包装了相关的表格元素,它们也不会继承扩展它们。

所以对于你的第一个例子,你的 DOM 是这样的:

<my-table>

浏览器通常不会将单元格连接到行和行连接到表格的任何操作都无法跨越这些影子 DOM 边界,并且 <my-table> #shadow-root <tr> <td>A</td> <td>B</td> </tr> </my-table> 的呈现方式就像它位于新文档片段的根部一样。< /p>

同样,第三次尝试的 DOM 如下所示:

<tr>

这些阴影根中的每一个都是一个新的孤立片段。

问题变成了你想用这个结构做什么?

您是否想要看起来像表格但对行和单元格使用自定义元素的内容,请考虑改用 <my-table> #shadow-root <table> <my-tr> #shadow-root <tr> <my-td> #shadow-root <td> 布局。它比表格强大得多,并且在自定义元素中,CSS 比相当不一致的 display: grid 得到更好的支持。

如果你想要一些结构为表格的东西,考虑把整个表格放在影子根中并将数据作为属性传递

display: table-cell

然后使用属性前缀调用它:

@customElement('my-table')
class MyTable 
  extends LitElement {
  render() {
    return html`
<table>
  ${this.items.map(i => html`
  <tr>
    <td>A</td>
    <td>B</td>
  </tr>`)}
</table>
    `;
  }

  @property({attribute: false})
  items: readonly RowRecordType[];
}

最后,如果您想扩展 <my-table .items=${theListOfRows}></my-table> ,您可以使用 <td> 语法添加到它,但这在规范中有点死胡同,是在 Safari 或 Opera 上根本不支持,其余部分则很不稳定。

您可以扩展单元格:

is=

然后做:

class MyCell
    extends HTMLTableCellElement { ...

customElements.define('my-cell', MyCell, { extends: 'td' });

但是,这不受 LitElement 支持,您最好直接实现您的自定义 Web 组件。