在LitElement的Shadow DOM中正确获取scrollHeight等滚动属性的方法
关于Shadow DOM中滚动属性获取的相关问题解答
两个写法是否等价?
二者完全不等价,具体差异如下:
documentElement是document对象的独有属性,对应页面顶层的<html>根节点,ShadowRoot本身不存在这个属性,所以调用this.shadowRoot.documentElement必然报错。this.shadowRoot.firstElementChild获取的是Shadow DOM挂载的第一个直接子元素,只有当你的Lit组件模板根节点唯一(比如最外层统一用一个容器元素包裹所有内容)时,才能刚好拿到你预期的元素,属于依赖节点结构的巧合写法,不是通用方案。
反例说明:如果你的Lit模板开头有注释节点、或者使用了多根模板(无包裹元素的Fragment),
firstElementChild要么返回非目标元素,要么直接返回null,会引发不可预期的bug。
Shadow DOM中获取滚动属性的最佳实践
根据你要获取的滚动属性所属范围,分两种场景处理:
- 获取全局页面的滚动属性
全局滚动属性绑定在顶层文档对象上,和Shadow DOM的隔离特性无关,直接沿用原来的写法即可,不需要从ShadowRoot中读取:
const {scrollHeight, scrollTop, clientHeight} = document.documentElement;
- 获取组件内部自定义容器的滚动属性
不要使用依赖节点顺序的firstElementChild写法,最稳妥的方式是给目标滚动容器绑定固定标识,两种推荐实现方式:
- 方式1:使用Lit的
ref指令绑定滚动容器(推荐,性能更高)
import {LitElement, html, ref, createRef} from 'lit'; class MyComponent extends LitElement { #scrollContainer = createRef(); render() { return html` <div ${ref(this.#scrollContainer)} style="overflow: auto; height: 400px;"> <!-- 组件内部内容 --> </div> `; } getScrollAttrs() { const el = this.#scrollContainer.value; if (!el) return {}; const {scrollHeight, scrollTop, clientHeight} = el; return {scrollHeight, scrollTop, clientHeight}; } }
- 方式2:给滚动容器加固定类名,用
querySelector匹配
// 模板中给容器加class:<div class="my-scroll-container" style="overflow: auto"></div> const container = this.shadowRoot.querySelector('.my-scroll-container'); const {scrollHeight, scrollTop, clientHeight} = container ?? {};
内容的提问来源于stack exchange,提问作者user3757849
相关产品推荐
相关产品推荐

