Lightning Web 组件调度标准 DOM 事件。组件还可以创建和调度自定义事件。使用事件向上传达组件包含层次结构。例如,子组件 调度一个事件,以告知其父组件 ,用户选择了它。c-todo-item
c-todo-app
Lightning Web 组件中的事件基于 DOM 事件构建,DOM 事件是每个浏览器中可用的 API 和对象的集合。
DOM 事件系统是一种包含这些元素的编程设计模式。
- 事件名称,称为类型
- 用于初始化事件的配置
- 发出事件的 JavaScript 对象
要创建事件,我们强烈建议使用界面。在 Lightning Web 组件中,提供跨浏览器的更一致的体验。它不需要设置或样板,它允许您通过属性传递任何类型的数据,这使得它很灵活。CustomEvent
CustomEvent
detail
Lightning Web 组件实现了该接口,允许它们调度事件、侦听事件和处理事件。EventTarget
提示
若要向下通信组件包含层次结构,请通过 HTML 属性将属性传递给子级,或调用其公共方法。要在组件之间进行通信,请使用 Lightning 消息服务或发布订阅实用程序。
创建和调度事件
在组件的 JavaScript 类中创建和调度事件。若要创建事件,请使用构造函数。若要调度事件,请调用该方法。CustomEvent()
EventTarget.dispatchEvent()
构造函数有一个必需的参数,该参数是指示事件类型的字符串。作为组件作者,您可以在创建事件时命名事件类型。您可以使用任何字符串作为事件类型。但是,我们建议您遵守 DOM 事件标准。CustomEvent()
- 没有大写字母
- 无空格
- 使用下划线分隔单词
不要在事件名称前面加上字符串 ,因为内联事件处理程序名称必须以字符串 开头。如果调用事件,则标记将为 。注意双倍的单词,这很令人困惑。on
on
onmessage
<c-my-component ononmessage={handleMessage}>
onon
使用自定义事件进行跨组件通信
示例:调度和处理事件
让我们跳到一些代码中。
该组件包含“上一个”和“下一个”按钮。当用户单击按钮时,组件将创建并调度事件。您可以将组件拖放到需要“上一个”和“下一个”按钮的任何组件中。该父组件侦听事件并处理它们。c-paginator
previous
next
paginator
<!-- paginator.html -->
<template>
<lightning-layout>
<lightning-layout-item>
<lightning-button
label="Previous"
icon-name="utility:chevronleft"
onclick={previousHandler}
></lightning-button>
</lightning-layout-item>
<lightning-layout-item flexibility="grow"></lightning-layout-item>
<lightning-layout-item>
<lightning-button
label="Next"
icon-name="utility:chevronright"
icon-position="right"
onclick={nextHandler}
></lightning-button>
</lightning-layout-item>
</lightning-layout>
</template>
当用户单击按钮时,将执行 or 函数。这些函数创建和调度 和 事件。previousHandler
nextHandler
previous
next
// paginator.js
import { LightningElement } from "lwc";
export default class Paginator extends LightningElement {
previousHandler() {
this.dispatchEvent(new CustomEvent("previous"));
}
nextHandler() {
this.dispatchEvent(new CustomEvent("next"));
}
}
这些事件是简单的“某事发生”事件。它们不会将数据有效负载传递到 DOM 树上,它们只是宣布用户单击了一个按钮。
让我们进入一个名为 的组件,它侦听并处理 和 事件。paginator
c-event-simple
previous
next
要侦听事件,请使用语法为 的 HTML 属性。由于我们的事件类型是 和 ,因此侦听器是 和 。oneventtype
previous
next
onprevious
onnext
<!-- eventSimple.html -->
<template>
<lightning-card title="EventSimple" icon-name="custom:custom9">
<div class="slds-m-around_medium">
<p class="slds-m-vertical_medium content">Page {page}</p>
<c-paginator onprevious={previousHandler} onnext={nextHandler}></c-paginator>
</div>
</lightning-card>
</template>
当收到 和 事件时,并增加和减少页码。c-event-simple
previous
next
previousHandler
nextHandler
// eventSimple.js
import { LightningElement } from "lwc";
export default class EventSimple extends LightningElement {
page = 1;
previousHandler() {
if (this.page > 1) {
this.page = this.page - 1;
}
}
nextHandler() {
this.page = this.page + 1;
}
}
提示
查看 github.com/trailheadapps/lwc-recipes
存储库中的 c-event-simple
组件和 c-paginator
组件。
在事件中传递数据
若要将数据传递到接收组件,请在构造函数中设置属性。接收组件访问事件侦听器的处理程序函数中属性中的数据。detail
CustomEvent
detail
注意
该接口对属性不施加任何类型要求或结构。但是,仅发送原始数据很重要。JavaScript 通过引用传递除基元之外的所有数据类型。如果组件在其属性中包含对象,则任何侦听器都可以在组件不知情的情况下更改该对象。这是一件坏事!最佳做法是仅发送基元,或者在将数据添加到属性之前将数据复制到新对象。将数据复制到新对象可确保仅发送所需的数据,并且接收方无法更改数据。CustomEvent
detail
detail
detail
让我们看一下 lwc-recipes 存储库中的组件。c-event-with-data

联系人列表中的每个项目都是一个嵌套组件。c-contact-list-item
该组件使用执行函数的事件侦听器将联系人姓名和图片包装在锚标记中。c-contact-list-item
onclick
selectHandler
<!-- contactListItem.html -->
<template>
<a href="#" onclick={selectHandler}>
<lightning-layout vertical-align="center">
<lightning-layout-item>
<img src={contact.Picture__c}></img>
</lightning-layout-item>
<lightning-layout-item padding="around-small">
<p>{contact.Name}</p>
</lightning-layout-item>
</lightning-layout>
</a>
</template>
当用户单击以选择联系人时,该组件将创建并调度被调用的 .该事件包括数据,即所选联系人的 ID。父级 , 使用联系人引用来显示有关联系人的详细信息。CustomEvent
selected
detail: this.contact.Id
c-event-custom
// contactListItem.js
import { LightningElement, api } from "lwc";
export default class ContactListItem extends LightningElement {
@api contact;
selectHandler(event) {
// Prevents the anchor element from navigating to a URL.
event.preventDefault();
// Creates the event with the contact ID data.
const selectedEvent = new CustomEvent("selected", { detail: this.contact.Id });
// Dispatches the event.
this.dispatchEvent(selectedEvent);
}
}
该组件侦听属性中的事件,并在事件处理程序中处理该事件。c-event-with-data
selected
onselected
contactSelected
<!-- eventWithData.html -->
<template>
<lightning-card title="EventWithData" icon-name="custom:custom9">
<lightning-layout class="slds-m-around_medium">
<lightning-layout-item>
<template lwc:if={listIsNotEmpty}>
<template for:each={contacts.data} for:item="contact">
<c-contact-list-item key={contact.Id} contact={contact} onselected={contactSelected}></c-contact-list-item>
</template>
</template>
</lightning-layout-item>
<lightning-layout-item class="slds-m-left_medium">
<template lwc:if={selectedContact}>
<img src={selectedContact.Picture__c}></img>
<p>{selectedContact.Name}</p>
<p>{selectedContact.Title}</p>
<p><lightning-formatted-phone value={selectedContact.Phone}></lightning-formatted-phone></p>
<p><lightning-formatted-email value={selectedContact.Email}></lightning-formatted-email></p>
</template>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</template>
在事件处理程序中,组件将属性分配给属性。它在通过 置备的阵列中查找具有该 ID 的联系人,并在模板中显示联系人的姓名、职务、电话和电子邮件。contactSelected
event.detail
contactId
contacts
@wire
// eventWithData.js
import { LightningElement, wire } from "lwc";
import getContactList from "@salesforce/apex/ContactController.getContactList";
export default class EventWithData extends LightningElement {
selectedContact;
@wire(getContactList) contacts;
contactSelected(event) {
const contactId = event.detail;
this.selectedContact = this.contacts.data.find((contact) => contact.Id === contactId);
}
get listIsNotEmpty() {
return this.contacts && Array.isArray(this.contacts.data) && this.contacts.data.length > 0;
}
}
提示
查看 github.com/trailheadapps/lwc-recipes 存储库中的 c-event-with-data
组件。
处理事件
有两种方法可以侦听事件:从组件的 HTML 模板以声明方式侦听事件,或者使用命令式 JavaScript API 以编程方式侦听事件。最好从 HTML 模板中监听,因为它减少了您必须编写的代码量。若要处理事件,请在组件的 JavaScript 类中定义方法。
以声明方式附加事件侦听器
在所有者组件的模板中以标记形式声明侦听器,在本例中为 .c-parent
<!-- parent.html -->
<template>
<c-child onnotification={handleNotification}></c-child>
</template>
在此示例中,在 JavaScript 文件中定义处理程序函数。handleNotification
c-parent
// parent.js
import { LightningElement } from "lwc";
export default class Parent extends LightningElement {
handleNotification() {
// Code runs when event is received
}
}
以编程方式附加事件侦听器
在 JavaScript 中定义侦听器和处理程序函数。c-parent
// parent.js
import { LightningElement } from "lwc";
export default class Parent extends LightningElement {
constructor() {
super();
this.template.addEventListener("notification", this.handleNotification);
}
handleNotification = () => {};
}
如果将同一侦听器重复添加到同一元素中,则浏览器将忽略重复项。
如果未删除事件侦听器,则可以选择在调用中内联代码。handleNotification
addEventListener()
this.template.addEventListener("notification", (evt) => {
console.log("Notification event", evt);
});
重要
不要使用 .这是一个反模式,因为返回一个新函数,因此组件不能使用相同的函数实例进行调用。由于组件不能使用相同的函数实例,因此侦听器会造成内存泄漏。addEventListener({eventName}, this.handleNotification.bind(this))
bind()
removeEventListener()
添加事件侦听器有两种语法。一个用于将事件侦听器添加到组件的影子边界内的元素,另一个用于将事件侦听器添加到模板不拥有的元素,例如,传递到槽中的元素。
要将事件侦听器添加到阴影边界内的元素,请使用 .template
this.template.addEventListener();
若要将事件侦听器添加到模板不拥有的元素,请直接调用。addEventListener
this.addEventListener();
获取对调度事件的组件的引用
若要获取对调度事件的对象的引用,请使用 Event.target
属性,该属性是事件的 DOM API 的一部分。
提示
lwc-recipes repo 中的几个配方使用 .若要查找示例,请在存储库中搜索 .Event.targetEvent.target
事件重定向
当事件冒泡 DOM 时,如果它越过阴影边界,则 的值会更改以匹配侦听器的范围。此更改称为“事件重定向”。事件被重新定位,因此侦听器无法看到调度事件的组件的影子 DOM。事件重定向保留了影子 DOM 封装。Event.target
让我们看一个简单的例子。
<!-- myButton.html -->
<template>
<button>{label}</button>
</template>
单击侦听器始终接收作为目标,即使单击发生在元素上也是如此。<my-button>
my-button
button
想象一下,一个事件是从组件中的元素调度出来的。在组件的影子 DOM 中,是 .但是对于包含组件中元素的侦听器来说,是 ,因为该元素无法看到影子 DOM。div
c-todo-item
Event.target
div
p
c-todo-app
Event.target
c-todo-item
p
c-todo-item
<c-todo-app>
#shadow-root
<div>
<p>Your To Do List</p>
</div>
<c-todo-item>
#shadow-root
<div>
<p>Go to the store</p>
</div>
</c-todo-item>
</c-todo-app>
有趣的是,对于 上的侦听器来说,是 ,而不是 ,因为 在阴影边界之外。c-todo-item
Event.target
c-todo-item
div
c-todo-item
侦听输入字段的更改
若要侦听模板中接受输入的元素(如文本字段 ( 或 ))的更改,请使用该事件。<input>
<lightning-input>
onchange
<!-- form.html -->
<template>
<input type="text" value={myValue} onchange={handleChange} />
</template>
// form.js
import { LightningElement } from "lwc";
export default class Form extends LightningElement {
myValue = "initial value";
handleChange(evt) {
console.log("Current value of the input: " + evt.target.value);
}
}
在此示例中,每次输入值更改时都会调用 JavaScript 文件中的方法。handleChange()
该属性表示输入元素的值。此属性值不会在每次更改时自动更新。myValue
您可能需要对用户输入的值进行额外验证,以便在用户键入时自动更正或限制某些值。若要与输入的当前值保持同步,请在方法中更新。以下代码通过删除字符串开头和结尾的空格来自动更正键入的值。用于获取输入字段的当前值。myValue
myValue
handleChange()
evt.target.value
// form.js
import { LightningElement } from "lwc";
export default class Form extends LightningElement {
myValue = "initial value";
handleChange(evt) {
const typedValue = evt.target.value;
const trimmedValue = typedValue.trim(); // trims the value entered by the user
if (typedValue !== trimmedValue) {
evt.target.value = trimmedValue;
}
this.myValue = trimmedValue; // updates the internal state
}
}
此示例演示如何将 input value 属性重置为行 中的修剪值。它还演示了如何使属性与规范化值保持同步,以防组件将来被重新冻结(加载新值)。evt.target.value = trimmedValue
myValue
注意
从通过模板定义的元素中更改属性可能会在组件中的其他位置产生不希望的副作用。在我们的示例中,元素的输入值属性从模板中定义的值更改为 。该示例更改模板 () 中使用的值,以使组件元素的状态保持同步。否则,模板解除冻结会在尝试将输入元素的状态与组件的状态进行协调时检测到属性值不匹配。这种不匹配会生成运行时警告,您需要调整组件或 JavaScript,以保持整个模板中数据的完整性。evt.target
myValue
删除事件侦听器
作为组件生命周期的一部分,该框架负责为您管理和清理侦听器。但是,如果您将侦听器添加到其他任何内容(如对象、对象等),则您有责任自行删除侦听器。window
document
要删除事件侦听器,请使用 disconnectedCallback
生命周期挂钩。
配置事件传播
触发事件后,它可以通过 DOM 向上传播。若要了解事件的处理位置,请了解事件的传播方式。
事件通过 DOM 冒泡;这就是孩子和父母的沟通方式——向下支撑,向上事件。当事件冒泡时,它将成为组件 API 的一部分,事件路径上的每个使用者都必须了解该事件。了解冒泡的工作原理非常重要,这样您就可以选择适用于您的组件的最具限制性的冒泡配置。
Lightning Web 组件事件的传播规则与 DOM 事件相同。Lightning Web 组件仅使用冒泡阶段。不支持调度事件或将侦听器添加到捕获阶段。简单地将事件的路径视为从组件开始,然后移动到其父组件,然后是祖父级,依此类推。
事件目标不会传播到组件实例的影子根之外。在组件外部,所有事件目标都是组件本身。但是,在影子树中,您可以处理来自树中特定目标的事件。根据事件的侦听器附加位置以及事件发生的位置,可以具有不同的目标。
注意
此内容改编自 Salesforce 开发人员博客文章 Lightning Web 组件中的事件如何冒泡。
创建事件时,请使用事件的两个属性和 定义事件传播行为。bubbles
composed
Event.bubbles
一个 Boolean 值,该值指示事件是否通过 DOM 冒泡。缺省值为 .false
Event.composed
一个 Boolean 值,该值指示事件是否可以穿过阴影边界。缺省值为 .false
若要获取有关事件的信息,请使用事件 Web API 的这些属性和方法。
Event.target
调度事件的元素。每个组件的内部 DOM 都封装在一个影子 DOM 中。阴影边界是常规 DOM(也称为轻量级 DOM)和阴影 DOM 之间的线。如果事件冒泡并越过阴影边界,则 value of 的值将更改为表示与侦听器位于同一作用域中的元素。事件重定向可保留组件封装,并防止暴露组件的内部。Event.target
例如,单击侦听器始终接收作为目标,即使单击发生在元素上也是如此。<my-button>my-buttonbutton<!-- myButton.html --> <template> <button>{label}</button> </template>
Event.currentTarget
当事件遍历 DOM 时,此属性始终引用事件处理程序附加到的元素。Event.composedPath()
当事件遍历 DOM 时,将在其上调用侦听器的事件目标的数组。
静态成分
静态合成不使用插槽。在这个简单的例子中,compose ,而 compose 。c-app
c-parent
c-child
<c-app onbuttonclick={handleButtonClick}></c-app>
应用程序中的父组件处理按钮单击。
<!-- app.html -->
<template>
<h2>My app</h2>
<c-parent onbuttonclick={handleButtonClick}></c-parent>
</template>
父组件包含一个带有子组件的包装器,这两个组件都侦听按钮单击事件。
<!-- parent.html -->
<template>
<h3>I'm a parent component</h3>
<div class="wrapper" onbuttonclick={handleButtonClick}>
<c-child onbuttonclick={handleButtonClick}></c-child>
</div>
</template>
子组件包含带有处理程序的按钮。onclick
<!-- child.html -->
<template>
<h3>I'm a child component</h3>
<button onclick={handleClick}>click me</button>
</template>
// child.js
handleClick() {
const buttonclicked = new CustomEvent('buttonclick', {
//event options
});
this.dispatchEvent(buttonclicked);
}
该示例从单击按钮时触发事件 。事件侦听器为以下元素上的自定义事件附加:buttonclick
c-child
body
c-app
主机c-parent
div.wrapper
c-child
主机
扁平化的树如下所示:
<body>
<!-- Listening for buttonclick event -->
<c-app>
<!-- Listening for buttonclick event -->
#shadow-root
| <h2>My app</h2>
| <c-parent>
| <!-- Listening for buttonclick event -->
| #shadow-root
| | <h3>I'm a parent component</h3>
| | <div class="wrapper">
| | <!-- Listening for buttonclick event -->
| | <c-child>
| | #shadow-root
| | | <!-- Listening for buttonclick event -->
| | | <h3>I'm a child component</h3>
| | | <button>click me</button>
| | </c-child>
| | </div>
| </c-parent>
</c-app>
</body>
气泡:假,组合:假
默认配置。该事件不会通过 DOM 冒泡,也不会越过阴影边界。侦听此事件的唯一方法是直接在调度事件的组件上添加事件侦听器。
建议使用此配置,因为它的中断最小,并且为组件提供最佳封装。
事件最多只能冒泡。c-child
<body>
<c-app>
#shadow-root
| <c-parent>
| #shadow-root
| | <div class="wrapper">
| | <c-child>
| | <!-- Event bubbles up here -->
| | #shadow-root
| | | <h3>I'm a child component</h3>
| | | <button>click me</button>
| | </c-child>
| | </div>
| </c-parent>
</c-app>
</body>
检查处理程序会在事件上返回这些值。c-child
event.currentTarget
=c-child
event.target
=c-child
从这里开始,您可以开始实现更宽松的配置,如以下几节所示。
提示
lwc-recipes 存储库中的 c-event-with-data
组件使用 c-contact-list-item
组件,该组件使用 和 创建事件。bubbles: falsecomposed: false
气泡:真,组合:假
事件通过 DOM 冒泡,但不会越过影子边界。因此,两者都可以对事件做出反应。c-child
div.wrapper
<body>
<c-app>
#shadow-root
| <c-parent>
| #shadow-root
| | <div class="wrapper">
| | <!-- Event bubbles up here -->
| | <c-child>
| | <!-- Event bubbles up here -->
| | #shadow-root
| | | <h3>I'm a child component</h3>
| | | <button>click me</button>
| | </c-child>
| | </div>
| </c-parent>
</c-app>
</body>
事件处理程序返回以下内容。
C-Child
处理程序
event.currentTarget
=c-child
event.target
=c-child
div.childWrapper
处理程序
event.currentTarget
=div.childWrapper
event.target
=c-child
使用此配置有两个用例。
- 创建内部活动若要在组件的模板中冒泡事件,请在模板中的元素上调度该事件。该事件仅冒泡到模板内元素的祖先。当事件到达阴影边界时,它将停止。
// myComponent.js this.template.querySelector("div").dispatchEvent(new CustomEvent("notify", { bubbles: true }));
必须在 中处理该事件。包含组件中的处理程序不会执行,因为事件不会越过阴影边界。myComponent.js
<!-- container.html --> <template> <!-- handleNotify doesn’t execute --> <c-my-component onnotify={handleNotify}></c-my-component> </template>
- 将事件发送到组件的祖父级如果将组件传递到槽中,并且您希望将该组件中的事件冒泡到包含该组件的模板,请在主机元素上调度该事件。该事件仅在包含组件的模板中可见。让我们看一下从 lwc-recipes 存储库中的组件中删节的示例代码。从子级到祖父级的组件层次结构是 。
eventBubblingc-contact-list-item-bubbling -> lightning-layout-item -> c-event-bubbling
该组件调度一个调用 的自定义事件。c-contact-list-item-bubblingcontactselectbubbles: true
事件侦听器位于其父级 上,事件在其祖父级 中处理。oncontactselectlightning-layout-itemc-event-bubbling<!-- eventBubbling.html --> <template> <lightning-card title="EventBubbling" icon-name="standard:logging"> <template lwc:if={contacts.data}> <lightning-layout class="slds-var-m-around_medium"> <!-- c-contact-list-item-bubbling emits a bubbling event so a single listener on a containing element works --> <lightning-layout-item class="wide" oncontactselect={handleContactSelect}> <template for:each={contacts.data} for:item="contact"> <c-contact-list-item-bubbling class="slds-show slds-is-relative" key={contact.Id} contact={contact} ></c-contact-list-item-bubbling> </template> </lightning-layout-item> </lightning-layout> </template> </lightning-card> </template>// contactListItemBubbling.js import { LightningElement, api } from "lwc"; export default class ContactListItemBubbling extends LightningElement { @api contact; handleSelect(event) { // Prevent default behavior of anchor tag click which is to navigate to the href url event.preventDefault(); const selectEvent = new CustomEvent("contactselect", { bubbles: true, }); this.dispatchEvent(selectEvent); } }
气泡:真,组合:真
事件通过 DOM 冒泡,越过影子边界,然后继续冒泡通过 DOM 冒泡到文档根目录。
重要
如果事件使用此配置,则事件类型将成为组件公共 API 的一部分。它还强制使用组件及其所有祖先将事件作为其 API 的一部分包含在内。
由于此配置将事件一直冒泡到文档根目录,因此可能会导致名称冲突。名称冲突可能会导致触发错误的事件侦听器。
<body>
<!-- Event bubbles up here -->
<c-app>
<!-- Event bubbles up here -->
#shadow-root
| <c-parent>
| <!-- Event bubbles up here -->
| #shadow-root
| | <div class="wrapper">
| | <!-- Event bubbles up here -->
| | <c-child>
| | <!-- Event bubbles up here -->
| | #shadow-root
| | | <h3>I'm a child component</h3>
| | | <button>click me</button>
| | </c-child>
| | </div>
| </c-parent>
</c-app>
</body>
如果确实使用此配置,请在事件类型前面加上命名空间,例如 。HTML 事件侦听器将具有尴尬的名称。mydomain__myevent
onmydomain__myevent
气泡:假,组合:真
Lightning Web 组件不使用此配置。
跨 DOM 进行通信
有两种方法可以在不在同一 DOM 树中的组件之间进行通信。使用 Lightning 消息服务 (),或使用遵循发布-订阅模式的单例库。lightning/messageService
使用 Lightning 消息服务
要在单个 Lightning 页面或多个页面的组件之间进行通信,请使用 Lightning 消息服务通过 Lightning 消息通道进行通信。优点是消息通道不限于单个页面。Lightning Experience 应用程序中侦听消息通道上事件的任何组件在收到消息时都会更新。它可以在 Lightning Web 组件、Aura 组件和 Visualforce 页面之间工作,可以在 Lightning Experience 中的任何选项卡或任何弹出窗口中使用。它也可以跨命名空间工作。有关更多信息,请参阅使用 Lightning 消息服务跨 DOM 进行通信。pubsub
使用 pubsub 模块
在不支持 Lightning 消息传递服务的容器中,使用该模块。从 github.com/developerforce/pubsub 下载模块。pubsub
在发布-订阅模式中,一个组件发布一个事件。其他组件订阅以接收和处理事件。订阅该事件的每个组件都会接收该事件。该模块将事件限制在单个页面中。pubsub
活动最佳实践
我们建议在处理事件时遵循这些最佳做法。CustomEvent.detail
要将数据传达给同一影子树中的元素,请不要添加到 .事件的使用者可以使用 .myProperty
event.detail
event.target.myProperty
若要将数据传达给不在同一影子树中的元素,请使用 .在这些情况下,不起作用,因为侦听器看不到真正的目标。(当事件冒泡 DOM 时,如果它越过影子边界,则 的值会更改以匹配侦听器的范围。事件被重新定位,因此侦听器无法看到调度事件的组件的影子树。event.detail
event.target.*
Event.target
如果使用 ,请使用基元类型。JavaScript 通过引用传递除基元之外的所有数据类型。如果一个组件在其属性中包含一个对象,任何侦听器都可以在组件不知情的情况下改变该对象,这是一件坏事!detaildetail
使用非基元类型时,可以避免泄漏内部状态。在向属性添加数据之前,请将其复制到新对象或数组。将数据复制到新对象可确保仅发送所需的数据,并且接收方无法更改数据。detail
不要包含非基元 from 或 in 。这些值被包裹在只读膜中。在 IE 11 中,当穿过 LWC 到 Aura 桥时,只读膜丢失,这意味着可能会发生突变。@api@wiredetail
事件传播
使用配置了 和 的事件,因为它们的中断最小。这些事件不会通过 DOM 冒泡,也不会越过影子边界。bubbles: false
composed: false
不建议使用冒泡和组合事件,因为它们会冒泡整个 DOM 树,跨越阴影边界,并通过父组件(除非停止)。如果使用 和 配置事件,则事件类型将成为组件公共 API 的一部分。它还强制使用组件及其所有祖先将事件作为其 API 的一部分包含在内。这是一个需要注册的大型 API 合约。如果使用此配置,则事件类型应全局唯一。bubbles: true
composed: true