Lit框架下非父子独立Web Components组件如何实现相互通信?
Lit 非父子独立组件通信实现方案
方案1:全局自定义事件(轻量场景首选)
适用于仅需要单次触发、参数传递简单的场景,无需额外依赖,两个组件完全解耦。
实现步骤
- 发送方(nav-bar)点击汉堡按钮时,在全局window对象上派发自定义事件,可携带自定义参数
- 接收方(custom-menu)在组件挂载时监听该全局事件,销毁时移除监听避免内存泄漏,收到事件后更新自身响应式状态控制显隐
代码示例
nav-bar 组件逻辑
import { LitElement, html } from 'lit'; class NavBar extends LitElement { #handleHamburgerClick() { // 触发全局自定义事件 window.dispatchEvent(new CustomEvent('toggle-custom-menu', { detail: { show: true }, // 可自定义传递的参数,也可以做切换逻辑 bubbles: true, composed: true })); } render() { return html` <button @click=${this.#handleHamburgerClick}>汉堡按钮</button> <!-- 其余导航栏逻辑 --> `; } } customElements.define('nav-bar', NavBar);
custom-menu 组件逻辑
import { LitElement, html } from 'lit'; import { state } from 'lit/decorators/state.js'; class CustomMenu extends LitElement { @state() private _isShow = false; connectedCallback() { super.connectedCallback(); // 监听全局自定义事件 window.addEventListener('toggle-custom-menu', this.#handleToggleMenu); } disconnectedCallback() { super.disconnectedCallback(); // 组件销毁时移除监听,避免内存泄漏 window.removeEventListener('toggle-custom-menu', this.#handleToggleMenu); } #handleToggleMenu = (event) => { // 从事件参数中获取显隐状态,也可以直接实现切换逻辑:this._isShow = !this._isShow this._isShow = event.detail.show; } render() { return html` <div class=${this._isShow ? 'menu-visible' : 'menu-hidden'}> <!-- 菜单内容 --> </div> `; } } customElements.define('custom-menu', CustomMenu);
方案2:共享响应式Signal(多状态共享场景首选)
适用于多个独立组件需要共享多组状态、状态变更逻辑复杂的场景,维护性更高。
实现步骤
- 单独抽离公共状态模块,导出Lit Signal类型的响应式状态
- 发送方直接修改Signal的值触发状态更新
- 接收方通过装饰器监听Signal变化,自动更新视图
代码示例
公共状态模块 menu-state.js
import { signal } from '@lit-labs/signals'; // 导出全局响应式菜单显隐状态 export const isMenuShow = signal(false);
nav-bar 组件逻辑
import { LitElement, html } from 'lit'; import { isMenuShow } from './menu-state.js'; class NavBar extends LitElement { #handleHamburgerClick() { // 直接修改全局Signal值 isMenuShow.set(!isMenuShow.get()); } render() { return html` <button @click=${this.#handleHamburgerClick}>汉堡按钮</button> `; } } customElements.define('nav-bar', NavBar);
custom-menu 组件逻辑
import { LitElement, html } from 'lit'; import { watch } from '@lit-labs/signals'; import { isMenuShow } from './menu-state.js'; class CustomMenu extends LitElement { // 监听Signal变化,自动触发组件重渲染 @watch() get isMenuShow() { return isMenuShow.get(); } render() { return html` <div class=${this.isMenuShow ? 'menu-visible' : 'menu-hidden'}> <!-- 菜单内容 --> </div> `; } } customElements.define('custom-menu', CustomMenu);
方案选择建议
如果只是实现汉堡按钮控制菜单显隐的单一需求,选择方案1即可,实现成本最低且完全满足需求。如果后续还有多个跨组件共享状态的需求,可切换为方案2做统一状态管理。
内容的提问来源于stack exchange,提问作者grr412
相关产品推荐
相关产品推荐

