Web Components 是一种构建可复用且易于维护的前端组件的标准化技术。在实际应用中,组件之间的通信是非常重要的一部分。本文将介绍 Web Components 中常用的组件间通信技巧,涵盖了常见的父子组件通信、兄弟组件通信和跨层级通信等。
父子组件通信
在 Web Components 中,父子组件通信是最常见的一种通信方式。父组件可以通过属性传递数据给子组件,子组件可以通过事件将数据传递给父组件。
属性传递数据
父组件可以通过属性将数据传递给子组件。子组件可以通过 props
属性接收父组件传递的数据。
下面是一个简单的例子,父组件通过 message
属性传递数据给子组件:
<my-component message="Hello, world!"></my-component>
子组件可以通过 props
属性接收 message
属性的值:
// javascriptcn.com 代码示例 class MyComponent extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); const message = this.getAttribute('message'); shadow.innerHTML = ` <p>${message}</p> `; } } customElements.define('my-component', MyComponent);
事件传递数据
子组件可以通过事件将数据传递给父组件。子组件可以使用 dispatchEvent
方法触发自定义事件,父组件可以使用 addEventListener
方法监听自定义事件。
下面是一个简单的例子,子组件通过 my-event
自定义事件传递数据给父组件:
// javascriptcn.com 代码示例 class MyComponent extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <button>Click me</button> `; const button = shadow.querySelector('button'); button.addEventListener('click', () => { const event = new CustomEvent('my-event', { detail: { message: 'Hello, world!' } }); this.dispatchEvent(event); }); } } customElements.define('my-component', MyComponent);
父组件可以使用 addEventListener
方法监听 my-event
自定义事件,获取子组件传递的数据:
// javascriptcn.com 代码示例 <my-component></my-component> <script> const myComponent = document.querySelector('my-component'); myComponent.addEventListener('my-event', event => { const message = event.detail.message; console.log(message); }); </script>
兄弟组件通信
在 Web Components 中,兄弟组件通信是比较复杂的一种通信方式。兄弟组件之间不能直接通信,需要借助共同的父组件或事件总线等中间件。
共同的父组件
兄弟组件可以通过共同的父组件来通信。兄弟组件可以通过父组件的属性或事件来传递数据。
下面是一个简单的例子,两个兄弟组件共同的父组件是 my-app
,它们可以通过 message
属性和 my-event
自定义事件来传递数据:
// javascriptcn.com 代码示例 <my-app> <my-component-1 message="Hello"></my-component-1> <my-component-2></my-component-2> </my-app> <script> class MyApp extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <slot></slot> `; } } customElements.define('my-app', MyApp); class MyComponent1 extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); const message = this.getAttribute('message'); shadow.innerHTML = ` <p>${message}, world!</p> `; } } customElements.define('my-component-1', MyComponent1); class MyComponent2 extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <button>Click me</button> `; const button = shadow.querySelector('button'); button.addEventListener('click', () => { const event = new CustomEvent('my-event', { detail: { message: 'world' } }); this.dispatchEvent(event); }); } } customElements.define('my-component-2', MyComponent2); </script>
事件总线
兄弟组件可以通过事件总线来通信。事件总线是一个全局对象,用于接收和分发事件。
下面是一个简单的例子,事件总线是 window.eventBus
,两个兄弟组件可以通过 my-event
自定义事件来传递数据:
// javascriptcn.com 代码示例 <my-component-1></my-component-1> <my-component-2></my-component-2> <script> window.eventBus = { listeners: {}, addEventListener(type, listener) { if (!this.listeners[type]) { this.listeners[type] = []; } this.listeners[type].push(listener); }, removeEventListener(type, listener) { if (!this.listeners[type]) { return; } const index = this.listeners[type].indexOf(listener); if (index !== -1) { this.listeners[type].splice(index, 1); } }, dispatchEvent(event) { if (!this.listeners[event.type]) { return; } this.listeners[event.type].forEach(listener => { listener(event); }); } }; class MyComponent1 extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <button>Click me</button> `; const button = shadow.querySelector('button'); button.addEventListener('click', () => { const event = new CustomEvent('my-event', { detail: { message: 'Hello' } }); window.eventBus.dispatchEvent(event); }); } } customElements.define('my-component-1', MyComponent1); class MyComponent2 extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <p></p> `; window.eventBus.addEventListener('my-event', event => { const message = event.detail.message; shadow.querySelector('p').textContent = `${message}, world!`; }); } } customElements.define('my-component-2', MyComponent2); </script>
跨层级通信
在 Web Components 中,跨层级通信是比较复杂的一种通信方式。组件之间没有直接的联系,需要借助事件总线等中间件。
下面是一个简单的例子,跨层级通信的中间件是 window.eventBus
,父组件通过 my-event
自定义事件传递数据给子组件:
// javascriptcn.com 代码示例 <my-app></my-app> <script> window.eventBus = { listeners: {}, addEventListener(type, listener) { if (!this.listeners[type]) { this.listeners[type] = []; } this.listeners[type].push(listener); }, removeEventListener(type, listener) { if (!this.listeners[type]) { return; } const index = this.listeners[type].indexOf(listener); if (index !== -1) { this.listeners[type].splice(index, 1); } }, dispatchEvent(event) { if (!this.listeners[event.type]) { return; } this.listeners[event.type].forEach(listener => { listener(event); }); } }; class MyApp extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <my-component></my-component> `; } } customElements.define('my-app', MyApp); class MyComponent extends HTMLElement { constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <p></p> `; window.eventBus.addEventListener('my-event', event => { const message = event.detail.message; shadow.querySelector('p').textContent = `${message}, world!`; }); } } customElements.define('my-component', MyComponent); const event = new CustomEvent('my-event', { detail: { message: 'Hello' } }); window.eventBus.dispatchEvent(event); </script>
总结
本文介绍了 Web Components 中常用的组件间通信技巧,包括父子组件通信、兄弟组件通信和跨层级通信等。在实际应用中,选择合适的通信方式可以提高组件的复用性和维护性,使代码更加清晰和易于理解。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/656771f9d2f5e1655d044451