3

假设我有一个自定义元素。它由两部分组成,一个是打开和切换菜单的按钮,另一个是菜单本身。我想将菜单直接放在按钮 ( 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以某种方式填充变量。在这个例子中,它是 30px,但这实际上可以是任何数字。如果我想将菜单向右对齐,这同样适用于宽度。

我知道我可以先渲染标记,然后使用按钮获得对按钮的引用,this.root.querySelector("button").offsetHeight然后再重新渲染。尽管多亏了 lit-html 这会很有效,但我觉得这很脏并且在某些用例中会中断。

还有其他想法吗?

4

2 回答 2

3

如何在第一次渲染之前找出按钮的高度?

你不能因为渲染引擎设置了高度

还有一个潜在的问题

任何 CSS 更改都可以重新渲染您的按钮

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

所以在 connectedCallback() 你可以这样做:

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

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

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

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

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

在此处输入图像描述

于 2019-07-19T16:49:09.440 回答
0

我不知道这是否有帮助,因为它回避了知道按钮高度的问题,并且只是将菜单放置在按钮下方(或右侧),而不管高度如何。我更喜欢这种方法,以避免绝对定位和计算可能会因盒子大小问题而被抛弃。

如果您已经考虑过这一点并且确实需要按钮的尺寸,我们深表歉意,因为此解决方案实际上并未提供这些尺寸。


1) 将按钮包装在 div 中以强制在下方呈现菜单

button {
  height: 30px;
}

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

#menu-contents {
  height: 100px; padding: 3px; border: 1px solid gray;
}
<div id="dropdown-wrapper">
  <div>
    <button type="button">Dropdown</button>
  </div>
  <div id="dropdown-menu">
    <div id="menu-contents">menu here</div>
  </div>
</div>

2)删除下拉包装样式并使用“float:left”将菜单放置在右侧

button {
  height: 30px; float: left;
}

#dropdown-menu {
  float: left;
}

#menu-contents {
  height: 100px; padding: 3px; border: 1px solid gray;
}
<div id="dropdown-wrapper">
  <button type="button">Dropdown</button>
  <div id="dropdown-menu">
    <div id="menu-contents">menu here</div>
  </div>
</div>

于 2019-07-19T09:34:35.413 回答