【问题标题】:How to make custom table in custom element?如何在自定义元素中制作自定义表格?
【发布时间】:2019-04-04 15:13:18
【问题描述】:

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

首先。似乎浏览器只允许trtd 标签用于table

<!-- 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...),但我不知道这是正确的,这是唯一的方法。

还有其他方法可以创建自定义表格还是我的想法有问题?

【问题讨论】:

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


【解决方案1】:

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

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

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

所以对于您的第一个示例,您的 DOM 是这样的:

<my-table>
  #shadow-root
    <tr>
      <td>A</td>
      <td>B</td>
    </tr>
</my-table>

浏览器通常将单元格连接到行和将行连接到表的任何操作都无法跨越这些影子 DOM 边界,并且 &lt;tr&gt; 的呈现方式就像它位于新文档片段的根部一样。

同样,第三次尝试的 DOM 看起来像这样:

<my-table>
  #shadow-root
    <table>
       <my-tr>
         #shadow-root
           <tr>
             <my-td>
               #shadow-root
                 <td>

每个影子根都是一个新的孤立片段。

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

您是否想要看起来像表格但对行和单元格使用自定义元素的东西,请考虑改用display: grid 布局。它比表格更强大,而且在自定义元素中,CSS 比相当不一致的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>

最后,如果您想扩展 &lt;td&gt;,您可以使用 is= 语法添加它,但这在规范上有点死胡同,不支持全部都在 Safari 或 Opera 上,其余部分则很糟糕。

你可以扩展一个单元格:

class MyCell
    extends HTMLTableCellElement { ...

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

然后做:

<table>
  <tr>
    <td is="my-cell">A</td>
    <td is="my-cell">B</td>
  </tr>
</table>

但是,LitElement 不支持此功能,您最好直接实现自定义 Web 组件。

【讨论】:

    猜你喜欢
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    相关资源
    最近更新 更多