说我有一个自定义元素。它由两部分组成,一个用于打开和切换菜单的按钮,以及菜单本身。我想将菜单直接放在按钮(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可以提高效率,但我觉得这很脏,在某些用例中会中断。
还有其他想法吗?
答案 0 :(得分:2)
如何在第一次渲染之前找出按钮的高度?
您不能因为渲染引擎设置高度
还有另一个潜在问题
任何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中使用了几年。现在所有常绿的浏览器都支持它。
答案 1 :(得分: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”将菜单置于 right
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>