在自定义元素中获取元素引用
Getting an element reference in a Custom Element
假设我有一个自定义元素。它由两部分组成,一个用于打开和切换菜单的按钮以及菜单本身。我想将菜单直接放在按钮下方 (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 这会很有效,但我觉得这很脏并且在某些用例中会中断。
还有其他想法吗?
我不知道这是否有帮助,因为它回避了知道按钮高度的问题,只是将菜单放在按钮下方(或右侧),而不管高度如何。我更喜欢这种方法,以避免可能因 box-sizing 问题而丢失的绝对定位和计算。
如果您已经考虑过这一点并且确实需要按钮的尺寸,我们深表歉意,因为此解决方案实际上并未提供这些尺寸。
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) 移除 dropdown-wrapper 样式并使用 "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>
How do I find out the button's height before the first render?
你不能因为渲染引擎设置了高度
还有一个潜在的问题
任何 CSS 更改都可以 re-render 您的按钮
(不是很新的)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
假设我有一个自定义元素。它由两部分组成,一个用于打开和切换菜单的按钮以及菜单本身。我想将菜单直接放在按钮下方 (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 这会很有效,但我觉得这很脏并且在某些用例中会中断。
还有其他想法吗?
我不知道这是否有帮助,因为它回避了知道按钮高度的问题,只是将菜单放在按钮下方(或右侧),而不管高度如何。我更喜欢这种方法,以避免可能因 box-sizing 问题而丢失的绝对定位和计算。
如果您已经考虑过这一点并且确实需要按钮的尺寸,我们深表歉意,因为此解决方案实际上并未提供这些尺寸。
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) 移除 dropdown-wrapper 样式并使用 "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>
How do I find out the button's height before the first render?
你不能因为渲染引擎设置了高度
还有一个潜在的问题
任何 CSS 更改都可以 re-render 您的按钮
(不是很新的)ResizeObserver 会通知您这些更改
所以在 connectedCallback() 中你可以这样做:
this.observer = new ResizeObserver(entries=>{
// check whether you need to (re)set stuff here
});
this.observer.observe(this)
请注意(这让我在前 15 分钟感到困惑)您在页面中注入的元素会立即触发 ResizeObserver
ResizeObserver 已经在 Chrome 中存在多年了。所有长青浏览器现在都支持它。