
Lit 如何用 lit-labs/scoped-registry-mixin 把自定义元素定义作用域限定在 Shadow Root 内【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit如果你在用 Lit 写组件时遇到过这个问题所有自定义元素都注册在浏览器全局的customElements注册表里标签名一旦撞车比如两个库都用了simple-greeting后注册的会覆盖先注册的或者根本无法注册。lit-labs/scoped-registry-mixin提供的ScopedRegistryHostmixin 可以让组件把自己用到的自定义元素注册到一个仅作用于自身 Shadow Root 的作用域注册表中标签名映射不再依赖全局注册表。有两点前提必须先看清楚Scoped Custom Element Registries 是一个浏览器 API 提案尚未在任何浏览器中实现因此ScopedRegistryHost依赖一个推测性的 polyfillwebcomponents/scoped-custom-element-registry生产环境使用需自行承担风险该包属于 Lit Labs为收集设计反馈而发布可能收到破坏性变更或停止支持。准备工作安装与依赖版本需要安装两个包npm install lit-labs/scoped-registry-mixin webcomponents/scoped-custom-element-registry第二个包是 polyfillREADME 明确说明由于提案尚未被浏览器原生实现ScopedRegistryHost必须配合该 polyfill 使用。版本兼容方面package.json 声明的依赖为lit:^2.0.0 || ^3.0.0lit/reactive-element:^1.0.0 || ^2.0.0CHANGELOG 中 1.0.3 版本的说明证实了这一范围是有意为之让仍停留在 lit v2 的项目无需升级到 v3 也能使用该包。使用步骤声明作用域内元素1. 引入 polyfillpolyfill 需要在应用入口以副作用方式引入。仓库测试文件scoped-registry-mixin_test.ts中的引入方式import webcomponents/scoped-custom-element-registry/scoped-custom-element-registry.min.js;2. 定义一个普通的被宿主元素测试文件中的SimpleGreeting就是一个标准的 LitElement它没有用customElements.define注册到全局class SimpleGreeting extends LitElement { private name: String; static override get properties() { return {name: {type: String}}; } constructor() { super(); this.name World; } override render() { return htmlspanhello ${this.name}!/span; } }3. 用 ScopedRegistryHost 包装宿主元素并声明元素映射mixin 新增了声明式的static elementDefinitions属性用来列出要限定在自身 Shadow DOM 作用域内的自定义元素import {LitElement, html} from lit; import {ScopedRegistryHost} from lit-labs/scoped-registry-mixin; import {SimpleGreeting} from ./simple-greeting.js; class ScopedComponent extends ScopedRegistryHost(LitElement) { // 这里的元素只会在本元素的 shadow root 作用域内 // 按给定标签名注册 static elementDefinitions { simple-greeting: SimpleGreeting, }; render() { return html simple-greeting idgreeting namescoped world /simple-greeting; } } customElements.define(scoped-component, ScopedComponent);宿主元素本身scoped-component仍然按常规方式注册到全局注册表只有elementDefinitions里列出的元素被限定在 Shadow Root 内。4. 理解 mixin 内部做了什么查看 scoped-registry-mixin.ts 的createRenderRoot()实现README 描述的四个行为与代码一一对应如果类上声明了elementDefinitions且registry尚未创建就new CustomElementRegistry()并逐个调用registry.define(tagName, klass)调用this.attachShadow({...shadowRootOptions, customElements: constructor.registry})把作用域注册表传给attachShadow()将 shadow root 赋值给this.renderOptions.creationScope使 lit-html 在该作用域内创建 DOM通过adoptStyles把静态样式应用到 render root。另外该文件扩展了ShadowRootInit的全局类型声明加上customElements?: CustomElementRegistry字段——这与测试中// ts-expect-error: customElements not yet in ShadowRoot type的注释一致说明该 API 的类型尚未进入标准定义。结果验证仓库的测试用例给出了四条可直接复用的判断方式scoped-registry-mixin_test.ts在支持该 API 的浏览器中逐条对应宿主元素拥有自己的注册表await scopedComponent.updateComplete后scopedComponent.shadowRoot.customElements应存在被宿主的元素不创建注册表shadow root 内的simple-greeting自身shadowRoot.customElements不存在——作用域只建在宿主一层被宿主的元素是作用域内定义的simpleGreeting instanceof SimpleGreeting为true说明它确实被升级为作用域注册表中的类而不是裸元素全局注册表不受影响在文档任意位置shadow root 之外插入simple-greeting得到的元素instanceof SimpleGreeting为false、instanceof HTMLElement为true——即全局位置仍是未升级的自定义元素作用域定义不会泄漏到全局。此外测试还验证了静态样式行为不受影响宿主声明的css样式如:host { color: #ff0000; }会被应用到 shadow root 内的元素上。限制与不支持的环境浏览器兼容性测试文件用canTest变量做环境判断要求window.ShadowRoot存在、未启用ShadyDOM即不支持 Shadow DOM 而走了 polyfill 的旧浏览器如 IE11 会跳过测试、且window.ShadowRootInit存在。你的运行环境不满足这些条件时作用域注册表机制不会生效相关行为无法验证API 状态Scoped Custom Element Registries 提案本身未定稿、无浏览器实现polyfill 是推测性的speculative。README 的警告原文是 Use this feature, and the polyfill in production code at your own risk使用范围当使用作用域元素注册表时shadow root 内用到的所有自定义元素都必须在该作用域内定义缺一个就无法升级。想进一步确认本包的实现与行为直接阅读上面链接的 README、mixin 源码 和 测试文件 即可。【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考