LWC子向父组件自定义事件通信两种方式差异疑问
LWC中子组件向父组件自定义事件通信的两种方式差异及疑问解答
两种通信方式概述
- 方式1:通过
this.addEventListener绑定监听
在父组件的生命周期钩子(比如renderedCallback)里,调用this.addEventListener来监听子组件派发的事件。 - 方式2:父组件模板中子组件标签直接绑定方法
像这样在父组件HTML里写<c-child-component-for-event-prop onpass={fetchValue}></c-child-component-for-event-prop>,直接把事件和父组件的处理方法关联起来。
疑问解答
疑问1:为什么用this.addEventListener时必须同时设bubbles: true和composed: true才能被父组件监听到?
LWC组件本身是基于Shadow DOM做隔离的,子组件内部派发的事件默认被锁在自己的Shadow树里。
- 只开
bubbles: true的话,事件只会在子组件的Shadow树内部向上冒泡,出不去Shadow DOM的边界,到不了父组件的DOM树里。 - 而
composed: true的作用就是让事件突破Shadow DOM的隔离,进入到父组件的DOM树里传播。
所以必须同时开这两个属性,父组件通过this.addEventListener(监听自身DOM树的事件)才能抓到子组件的事件。
你看到文档说“仅需bubbles=true”的场景,一般是指同一个Shadow DOM内部的事件冒泡,不是跨组件(跨Shadow DOM)的情况,这就是你产生误解的原因。
疑问2:为什么在子组件标签上直接绑定方法时,哪怕bubbles: false和composed: false也能被父组件监听到?
这种方式是LWC框架专门为父子组件通信设计的,和原生DOM的事件冒泡规则没关系:
- 当你在父组件模板里写
onpass={fetchValue}时,LWC框架会直接在子组件的宿主节点(也就是<c-child-component-for-event-prop>这个DOM元素)上注册监听,专门盯着子组件主动派发的这个自定义事件。 - 这种绑定是框架层面的直接关联,不管事件有没有冒泡或者能不能跨Shadow DOM,父组件都能接收到。
相关代码示例
子组件HTML
<template> <p>This is child P tag Made on 10/03/2025</p> <lightning-card> <lightning-button label="Child Component" onclick={handleClick}></lightning-button> <p>{messageFromChild}</p> </lightning-card> </template>
子组件JavaScript
import { LightningElement } from 'lwc'; export default class ChildComponentForEventProp extends LightningElement { message = 'This is from Child'; handleClick() { // 用于addEventListener方式的事件 const selectEvent = new CustomEvent("buttonclick", { bubbles: true, composed: true, detail: this.message, }); this.dispatchEvent(selectEvent); // 用于模板绑定方式的事件 const selectEventSec = new CustomEvent("pass", { bubbles: false, composed: false, detail: this.message, }); this.dispatchEvent(selectEventSec); } }
父组件HTML
<template> <lightning-card> <h1>Parent Component - {messageFromChild}</h1> <p>This is Parent P tag</p> <c-child-component-for-event-prop onpass={fetchValue}> </c-child-component-for-event-prop> </lightning-card> </template>
父组件JavaScript
import { LightningElement } from 'lwc'; export default class ParentComponentForEventProp extends LightningElement { messageFromChild; renderedCallback() { this.addEventListener('buttonclick', this.handleButtonClickNewN.bind(this), true); } handleButtonClickNewN(event) { console.log('Came TO PARENT'); this.messageFromChild = event.detail + ' New One'; } fetchValue(event) { console.log( 'Value from Child LWC is ' + event.detail ); this.messageFromChild = event.detail + 'VIA component definition method'; } }
内容的提问来源于stack exchange,提问作者user2456012
相关产品推荐
相关产品推荐

