假设我有一个自定义元素。它由两部分组成,一个用于打开和切换菜单的按钮,以及菜单本身。我想将菜单直接放置在按钮(position: absolute)下方,但是按钮的高度可以根据主题而有所不同。如何在第一次渲染之前找出按钮的高度?

简化示例:

import { render, html } from 'lit-html';

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

    this.root = this.attachShadow({ mode: "open" });

    this.update();
  }

  get template() {
    return html`
      <style>
        button {
          height: 30px;
        }

        #dropdown-wrapper {
          position: relative;
          display: inline-block;
        }

        #dropdown-menu {
          position: absolute;
          top: ${dynamicButtonHeight}px;
          left: 0;
        }
      </style>

      <div id="dropdown-wrapper">
        <button type="button">Dropdown</button>

        <div id="dropdown-menu">
          <slot></slot>
        </div>
      </div>
    `;
  }

  update() {
    render(this.template, this.root, { eventContext: this });
  }
}

如您在示例中看到的,我想知道按钮在初始渲染时的高度,并以某种方式填充dynamicButtonHeight变量。在此示例中,它是30像素,但实际上可以是任何数字。如果我想将菜单向右对齐,那么宽度也一样。

我知道我可以首先渲染标记,然后使用this.root.querySelector("button").offsetHeight获得对按钮的引用,然后再进行渲染。尽管使用lit-html可以提高效率,但是我觉得这很脏,在某些情况下无法使用。

还有其他想法吗?

最佳答案



您不能这样做,因为渲染引擎设置为高度

还有另一个潜在的问题

任何CSS更改都可以重新呈现您的按钮

(不是很新的)ResizeObserver会通知您这些更改

因此,在connectedCallback()内部,您可以执行以下操作:

this.observer = new ResizeObserver(entries=>{
  // check whether you need to (re)set stuff here
});
this.observer.observe(this)

注意(这让我在前15分钟感到困惑)您在页面中注入(inject)的元素立即触发ResizeObserver

ResizeObserver已经使用Chrome已有多年了。现在所有常绿浏览器都支持它。

https://developers.google.com/web/updates/2016/10/resizeobserver

https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

javascript - 在自定义元素中获取元素引用-LMLPHP

09-19 10:20