如果基本 Aura 组件使用 HTML 元素包装,以便您可以侦听组件上的 HTML 事件,请将事件处理程序移动到基本 Lightning Web 组件。例如,支持多个事件处理程序,但不支持 .但是,Aura 使您能够创建包装器来处理事件。lightning:inputonkeydowndivkeydown
许多基本的 Lightning Web 组件具有与 Aura 对应组件相同的功能和属性。有些有细微的差异。
Lightning Web 组件继承了全局 HTML 属性和事件,使其比 Aura 组件更具功能性和性能。组件引用未列出每个组件的全局 HTML 属性和事件。参见 MDN 上的全局属性和事件。
对于组件样式,基本 Aura 组件和 Lightning Web 组件都支持设计变体和 SLDS 实用程序类。基本 Aura 组件还支持使用您自己的类进行自定义样式设置。但是,Lightning Web 组件遵循影子 DOM 标准,这阻止了使用您自己的类进行自定义样式。某些基本 LWC 组件支持用于自定义样式的 SLDS 样式挂钩。请参阅使用 Lightning Design System 样式挂钩设置组件样式。
下表列出了 Aura 基本组件与其 Lightning Web 组件对应组件之间的使用差异。Aura组件遵循名称格式,使用冒号分隔命名空间和组件名称。Lightning Web 组件遵循名称格式,用破折号分隔命名空间和组件名称。namespace:componentNamenamespace-component-name
lightning:layout允许组件之间的 HTML 标记、文本、表达式和其他组件。 不允许在组件之间使用表达式或其他组件。但是,您可以在组件之间放置 HTML 标记和文本。lightning:layoutItemlightning-layoutlightning-layout-itemlightning-layout-item
lightning
layoutItem
layout-item
请参阅的差异。lightning-layout
lightning
listView
–
Lightning Web 组件尚不可用。
lightning
map
map
–
lightning
menuItem
menu-item
–
lightning
navigation
navigation模块
在 Aura 组件中,使用该组件访问导航服务。在 Lightning Web 组件中,在组件的 JavaScript 中导入模块。请参阅导航到页面、记录和列表。lightning:navigationlightning/navigation
lightning:recordEditForm不需要直接将组件嵌套在其中。您可以将组件嵌套在 HTML 标记或其他组件中,例如定制布局。 旨在用作 的子项。您可以嵌套在 HTML 标记或其他基本组件中,例如 within 中。但是,不能嵌套在自定义组件中。lightning:inputFieldlightning:inputFieldlightning:layoutlightning-input-fieldlightning-record-edit-formlightning-input-fieldlightning-layoutlightning-record-edit-formlightning-input-field
lightning
recordForm
record-form
–
lightning
recordViewForm
record-view-form
lightning:recordViewForm不需要您直接将组件嵌套在其中,尽管这是预期的用法。 必须是 的子项。不要嵌套在另一个元素中,例如 .您可以将其放置在容器中,例如 within 中。lightning:outputFieldlightning-output-fieldlightning-record-view-formlightning-output-fieldlightning-layoutlightning-record-view-form
lightning
relativeDateTime
relative-date-time
–
lightning
select
–
Lightning Web 组件尚不可用。在移动环境中,使用本机元素。在桌面环境中,请考虑使用 Lightning Web 组件。要支持多选,请使用 .<select>lightning-comboboxlightning-dual-listbox
force:inputField已被 in Aura 取代。要根据字段类型创建可编辑字段,请使用 Lightning Web 组件或其对应的 Lightning Web 组件。lightning:inputFieldlightning:inputFieldlightning:recordEditForm
force
outputField
output-field
force:outputField已被 in Aura 取代。要根据字段类型创建只读字段,请使用 或其对应的 Lightning Web 组件。lightning:outputFieldlightning:outputFieldlightning:recordViewForm
force
recordData
@wire
请参阅了解 Wire Service。
force
recordEdit
record-edit-form
force:recordEdit已替换为 。lightning:recordEditForm
force
recordView
record-view-form
force:recordView已替换为 。lightning:recordViewForm
ltng
require
platformResourceLoader模块
在 Aura 组件中,将标记添加到组件标记以引用外部静态资源。在 Lightning Web 组件中,将模块导入组件的 JavaScript 中。请参阅使用第三方 JavaScript 库。<ltng:require>lightning/platformResourceLoader
<aura:component>
<!-- start of component body facet-->
<p>Feeling hungry?</p>
<c:bacon />
<c:lettuce />
<c:tomato />
<!-- end of component body facet -->
</aura:component>
构建 Aura 组件还是 Lightning Web 组件?
您可能渴望了解更多信息,甚至可能在阅读了有关 Aura 中的方面后享用午餐。现在,让我们看看您决定构建 Aura 组件还是 Lightning Web 组件的方面因素。
如果您正在构建一个新的 Lightning Web 组件,该组件需要其主体中的其他子组件,则这些子组件也必须是 Lightning Web 组件。请记住,Lightning Web 组件不能包含 Aura 组件。
想象一下,一个 Lightning Web 组件是嵌套组件树中最外层的组件。将闪电网络组件视为俄罗斯套娃中最大的娃娃,也称为俄罗斯套娃。俄罗斯套娃包含一组嵌套娃娃,每个娃娃包含一个较小的娃娃。如果最大的玩偶是 Lightning Web 组件,那么较小的嵌套玩偶都不能是 Aura 组件。
示例:将组件传递到插槽中
考虑一个允许在其主体中使用其他组件的 Lightning Web 组件。标记是所有者组件可以将标记传递到其中的占位符。c-wrapper<slot>
使用 Lightning Out 在 Salesforce 服务器之外运行组件。无论是在 Heroku 上运行的 Node.js 应用程序,还是防火墙内的部门服务器,都可以将您的 Lightning Web 组件添加到独立的 Aura 依赖项应用程序中。然后,无论用户身在何处,都可以运行它们。
注意
此版本包含 Lightning Out 的测试版,这意味着它是一项具有已知限制的高质量功能。您可以在 IdeaExchange 上提供对 Lightning Out 的反馈和建议。
开发可部署在任何地方的 Lightning Web 组件通常与开发它们在 Salesforce 中运行相同。您所知道的有关组件开发的所有内容仍然适用。区别在于如何将应用嵌入远程 Web 容器或源服务器。
以 JavaScript 库的形式将 Lightning Out 添加到外部应用程序,这些库包含在源服务器上的页面中。添加标记以配置和激活您的独立 Aura 应用程序。初始化后,Lightning Out 会通过安全连接拉入 Lightning 组件应用程序,将其启动,然后将其插入到运行它的页面的 DOM 中。到达此点后,您的 Lightning Web 组件代码将接管并运行节目。
注意
此方法不同于使用 iframe 嵌入应用。通过 Lightning Out 运行的 Lightning Web 组件是页面上的正式公民。如果您愿意,您可以启用独立 Aura 应用程序与您嵌入的页面或应用程序之间的交互。此交互使用 Lightning 事件进行处理。
要在 Aura 应用程序或 Aura 组件中引用 Lightning Web 组件,请使用命名约定。<namespace:camelCaseComponentName>
使用独立的 Aura 依赖应用程序
独立的 Aura 依赖项应用必须执行以下操作。
将访问控制设置为 。GLOBAL
从 或 扩展。ltng:outAppltng:outAppUnstyled
将调用 中引用的每个组件作为依赖项列出。$Lightning.createComponent()
在此示例中,是您计划使用 在源服务器上创建的顶级 Lightning Web 组件。使用 为添加到页面的每个组件创建一个依赖项。<c:myAppComponent>$Lightning.createComponent()$Lightning.createComponent()
注意
不要担心顶级组件中使用的组件。该框架处理子组件的依赖项解析。
独立的 Aura 依赖应用程序不是普通的 Aura 应用程序,您不应将其视为一个应用程序。仅用于指定 Lightning Out 应用的依赖项。
特别要注意以下几点。
无法将模板添加到独立的 Aura 依赖项应用。
添加到独立 Aura 依赖项应用正文的内容不会呈现。
定义样式依赖关系
您有两种选项可用于设置 Lightning Out 应用程序的样式:Salesforce Lightning Design System 和 unstyled。Lightning Design System 样式是默认样式,Lightning Out 会自动将当前版本的 Lightning Design System 包含在使用 Lightning Out 的页面上。要省略 Lightning Design System 资源并完全控制您的样式,也许是为了匹配源服务器的样式,请将您的依赖项应用程序设置为 extend from 而不是 .ltng:outAppUnstyledltng:outApp
闪电输出标记
Lightning Out 需要在页面上添加一些简单的标记,并使用两个简单的 JavaScript 函数激活。
Lightning Out 库中的标记和 JavaScript 函数是 Lightning Out 唯一特有的功能。其他一切都是您已经知道和喜爱的 Lightning Web 组件代码。
将 Lightning Out 库添加到页面
通过将 Lightning Out JavaScript 库包含在托管独立 Aura 依赖项应用程序的应用程序或页面中,启用源服务器以与 Lightning Out 一起使用。包含库需要一行标记。
<script>
$Lightning.use(
"c:locatorApp", // name of the Lightning app
function () {
// Callback once framework and app loaded
$Lightning.createComponent(
"c:storeLocatorMain", // top-level component of your app
{}, // attributes to set on the component when created
"lightningLocator", // the DOM location to insert the component
function (cmp) {
// callback when component is created and active on the page
},
);
},
"https://universalcontainers.force.com/ourstores/", // Site endpoint
);
</script>
闪电输出注意事项和限制
使用 Lightning Out 创建应用程序通常与使用 Lightning Web 组件创建任何应用程序一样。但是,由于您的组件在 Salesforce 外部运行,因此您需要注意一些问题。
您必须注意的问题可以分为两类。
使用闪电输出的注意事项
由于 Lightning Out 应用程序在任何 Salesforce 容器之外运行,因此您需要牢记并可能解决一些事项。浏览器支持
Lightning Out 支持与 Lightning Experience 相同的浏览器。这种支持意味着您的 Lightning Out 应用程序和组件会在这些浏览器中加载。但是,如果组件或功能不支持特定浏览器,则该组件或功能在 Lightning Out 中也无法运行。性能
Lightning Out 无法从 Lightning Experience 的许多缓存功能中受益,因此启动和性能通常较慢。浏览器第三方 Cookie
Lightning 组件在用户的浏览器中设置 Cookie。由于 Lightning Out 在 Salesforce 之外运行 Lightning 组件,因此这些 Cookie 是“第三方”Cookie。要使 Lightning Out 应用程序能够与第三方 Cookie 配合使用,请参阅闪电输出要求。认证
没有 Salesforce 容器可以为您处理身份验证,因此您必须自己处理。Authentication from Lightning Out 中详细讨论了这一重要主题。
标准组件的局限性
虽然 Lightning Out 的核心功能稳定且完整,但我们仍在努力与其他 Salesforce 功能进行一些交互。
这些功能中最主要的是内置于 Lightning 组件框架中的标准组件。许多标准组件在独立环境中使用时无法正常运行,例如 Lightning Out 和基于 Lightning Out 的 Lightning Web Components for Visualforce。此限制是因为组件依赖于容器中的可用资源。one.app
// c/myApp.js
import { LightningElement } from "lwc";
import LightningAlert from "lightning/alert";
export default class MyApp extends LightningElement {
async handleAlertClick() {
await LightningAlert.open({
message: "This is the alert message.",
theme: "error", // a red theme intended for error states
label: "Error!", // this is the header text
});
// alert modal has been closed
}
}
// c/myApp.js
import { LightningElement } from "lwc";
import LightningConfirm from "lightning/confirm";
export default class MyApp extends LightningElement {
async handleConfirmClick() {
const result = await LightningConfirm.open({
message: "This is the confirmation message.",
variant: "headerless",
label: "This is the aria-label value",
// label value isn't visible in the headerless variant
});
// confirm modal has been closed
}
}
import { LightningElement } from "lwc";
import LightningPrompt from "lightning/prompt";
export default class MyApp extends LightningElement {
handlePromptClick() {
LightningPrompt.open({
message: "This is the prompt message.",
//theme defaults to "default"
label: "Please Respond!", // this is the header text
defaultValue: "Optional initial input value",
}).then((result) => {
// prompt modal has been closed
});
}
}
// navigationLinkExample.js
import { LightningElement, wire } from "lwc";
import { NavigationMixin } from "lightning/navigation";
export default class NavigationLinkExample extends NavigationMixin(LightningElement) {
url;
connectedCallback() {
// Store the PageReference in a variable to use in handleClick.
// This is a plain Javascript object that conforms to the
// PageReference type by including 'type' and 'attributes' properties.
// The 'state' property is optional.
this.accountHomePageRef = {
type: "standard__objectPage",
attributes: {
objectApiName: "Account",
actionName: "home",
},
};
this[NavigationMixin.GenerateUrl](this.accountHomePageRef).then((url) => (this.url = url));
}
handleClick(evt) {
// Stop the event's default behavior.
// Stop the event from bubbling up in the DOM.
evt.preventDefault();
evt.stopPropagation();
// Navigate to the Account Home page.
this[NavigationMixin.Navigate](this.accountHomePageRef);
}
}
添加查询参数
若要向 URL 添加查询参数,请更新该属性。导航服务使用 a 来生成 URL。属性的键值对将序列化为 URL 查询参数。查询参数描述页面并形成用户可以保存或添加书签的更具体的 URL。PageReference.statePageReferencestate
// pageStateChangeExample.js
import { LightningElement, wire } from "lwc";
import { CurrentPageReference, NavigationMixin } from "lightning/navigation";
export default class PageStateChangeExample extends NavigationMixin(LightningElement) {
// Declare the currentPageReference variable in order to track it
currentPageReference;
// Injects the page reference that describes the current page
@wire(CurrentPageReference)
setCurrentPageReference(currentPageReference) {
this.currentPageReference = currentPageReference;
if (this.connected) {
// We need to have the currentPageReference, and to be connected before
// we can use NavigationMixin
this.generateUrls();
} else {
// NavigationMixin doesn't work before connectedCallback, so if we have
// the currentPageReference, but haven't connected yet, queue it up
this.generateUrlOnConnected = true;
}
}
showPanelUrl;
noPanelUrl;
// Determines the display for the component's panel
get showPanel() {
// Derive this property's value from the current page state
return this.currentPageReference && this.currentPageReference.state.c__showPanel == "true";
}
generateUrls() {
this[NavigationMixin.GenerateUrl](this.showPanelPageReference).then(
(url) => (this.showPanelUrl = url),
);
this[NavigationMixin.GenerateUrl](this.noPanelPageReference).then(
(url) => (this.noPanelUrl = url),
);
}
// Returns a page reference that matches the current page
// but sets the 'c__showPanel' page state property to 'true'
get showPanelPageReference() {
return this.getUpdatedPageReference({
c__showPanel: "true", // Value must be a string
});
}
// Returns a page reference that matches the current page
// but removes the 'c__showPanel' page state property
get noPanelPageReference() {
return this.getUpdatedPageReference({
// Removes this property from the state
c__showPanel: undefined,
});
}
// Utility function that returns a copy of the current page reference
// after applying the stateChanges to the state on the new copy
getUpdatedPageReference(stateChanges) {
// The currentPageReference property is read-only.
// To navigate to the same page with a modified state,
// copy the currentPageReference and modify the copy.
return Object.assign({}, this.currentPageReference, {
// Copy the existing page state to preserve other parameters
// If any property on stateChanges is present but has an undefined
// value, that property in the page state is removed.
state: Object.assign({}, this.currentPageReference.state, stateChanges),
});
}
connectedCallback() {
this.connected = true;
// If the CurrentPageReference returned before this component was connected,
// we can use NavigationMixin to generate the URLs
if (this.generateUrlOnConnected) {
this.generateUrls();
}
}
handleShowPanelClick(evt) {
evt.preventDefault();
evt.stopPropagation();
// This example passes true to the 'replace' argument on the navigate API
// to change the page state without pushing a new history entry onto the
// browser history stack. This prevents the user from having to press back
// twice to return to the previous page.
this[NavigationMixin.Navigate](this.showPanelPageReference, true);
}
handleNoPanelClick(evt) {
evt.preventDefault();
evt.stopPropagation();
this[NavigationMixin.Navigate](this.noPanelPageReference, true);
}
}
导航到不同的页面类型
导航服务支持 Lightning 中不同类型的页面。每种类型都支持一组不同的特性和状态属性。这两个 API 都支持这些类型。PageReferencePageReference
示例:导航到页面
让我们看一个示例,说明如何创建导航到页面的按钮。
我们的示例有一个组件,它是 Salesforce 应用程序中的一个页面。在页面底部,有一个带有标签 Next 的组件。可以在每个页面的底部使用该组件,让用户浏览应用程序。welcomenavtabnavtab
<!-- welcome.html -->
<!-- lots and lots of code removed for brevity -->
<div class="slds-m-vertical_large">
<c-navtab tab-name="lightning_components" label="Next"></c-navtab>
</div>
该组件自定义组件以导航到应用程序中的下一页。使用者指定 a 和 a 。c-nav-tablightning-buttontab-namelabel
// navigationToPagesExample.js
import { LightningElement, wire } from "lwc";
import { NavigationMixin } from "lightning/navigation";
export default class NavigationToPagesExample extends NavigationMixin(LightningElement) {
navigateToObjectHome() {
// Navigate to the Case object home page.
this[NavigationMixin.Navigate]({
type: "standard__objectPage",
attributes: {
objectApiName: "Case",
actionName: "home",
},
});
}
navigateToListView() {
// Navigate to the Contact object's Recent list view.
this[NavigationMixin.Navigate]({
type: "standard__objectPage",
attributes: {
objectApiName: "Contact",
actionName: "list",
},
state: {
// 'filterName' is a property on the page 'state'
// and identifies the target list view.
// It may also be an 18 character list view id.
filterName: "Recent", // or by 18 char '00BT0000002TONQMA4'
},
});
}
navigateToNewRecordPage() {
// Opens the new Account record modal
// to create an Account.
this[NavigationMixin.Navigate]({
type: "standard__objectPage",
attributes: {
objectApiName: "Account",
actionName: "new",
},
});
}
navigateToRecordViewPage() {
// View a custom object record.
this[NavigationMixin.Navigate]({
type: "standard__recordPage",
attributes: {
recordId: "a03B0000002tEurIAE",
objectApiName: "namespace__ObjectName", // objectApiName is optional
actionName: "view",
},
});
}
navigateToRecordEditPage() {
// Opens the Account record modal
// to view a particular record.
this[NavigationMixin.Navigate]({
type: "standard__recordPage",
attributes: {
recordId: "001B000000ZBz22IAD",
objectApiName: "Account", // objectApiName is optional
actionName: "edit",
},
});
}
navigateToRelatedList() {
// Navigate to the CaseComments related list page
// for a specific Case record.
this[NavigationMixin.Navigate]({
type: "standard__recordRelationshipPage",
attributes: {
recordId: "500xx000000Ykt4AAC",
objectApiName: "Case",
relationshipApiName: "CaseComments",
actionName: "view",
},
});
}
navigateToTabPage() {
// Navigate to a specific CustomTab.
this[NavigationMixin.Navigate]({
type: "standard__navItemPage",
attributes: {
// CustomTabs from managed packages are identified by their
// namespace prefix followed by two underscores followed by the
// developer name. E.g. 'namespace__TabName'
apiName: "CustomTabName",
},
});
}
navigateToWebPage() {
// Navigate to a URL
this[NavigationMixin.Navigate](
{
type: "standard__webPage",
attributes: {
url: "http://salesforce.com",
},
},
true, // Replaces the current page in your browser history with the URL
);
}
}
lightning/pageReferenceUtils 模块提供了 and 函数,用于将默认字段值编码为字符串并对其进行解码。将编码字符串分配给页面引用中的属性。encodeDefaultFieldValues()decodeDefaultFieldValues()pageReference.state.defaultFieldValuesstandard__objectPage
该调用将创建一个带有“Press Me!”标签的按钮。该按钮入到 ID 为 的 DOM 元素中。在页面上添加按钮并处于活动状态后,将调用回调函数并执行语句。回调接收创建的组件作为其唯一参数。在这个简单示例中,该按钮未配置为执行任何操作。$Lightning.createComponent()lightningvfconsole.log()
<targetConfigs>
<targetConfig targets="lightningCommunity__Default">
<property
name="recordId"
type="String"
label="Record Id"
description="Automatically bind the page's record id to the component variable"
default="{!recordId}"
/>
</targetConfig>
</targetConfigs>
若要获取记录 ID 和对象 API 名称,请公开 and 作为属性。请参阅使组件了解其记录上下文和使组件了解其对象上下文。recordIdobjectApiName
此示例显示当前记录的记录 ID 和对象 API 名称。它还返回当前页面引用,该引用描述当前页面及其状态。
<template>
<p>These two fields are auto-populated based on the record context:</p>
<p>RecordId: <i>{recordId}</i>, objectApiName: <i>{objectApiName}</i></p>
<p>{pageRefString}</p>
</template>
import { LightningElement, api, wire } from "lwc";
import { CurrentPageReference } from "lightning/navigation";
export default class RecordContextAction extends LightningElement {
@api recordId;
@api objectApiName;
@wire(CurrentPageReference)
pageRef;
get pageRefString() {
return JSON.stringify(this.pageRef);
}
}
创建 Headless 快速操作
无头快速操作在 Lightning Web 组件中执行自定义代码。与屏幕操作不同,无头操作不会打开模式窗口。
要使您的组件用作无外设快速操作,请配置目标。请参阅配置组件以执行快速操作。
与记录页面上的其他 Lightning Web 组件不同,LWC 快速操作不会传入 .如果需要访问 ,请在代码中设置 的值。recordIdconnectedCallback()recordIdrecordId
_recordId;
set recordId(recordId) {
if (recordId !== this._recordId) {
this._recordId = recordId;
实现 invoke()
在您的 Lightning Web 组件中,始终公开为无头快速操作的公共方法。每次触发快速操作时,都会执行该方法。invoke()invoke()
import { LightningElement, api } from "lwc";
export default class HeadlessSimple extends LightningElement {
@api invoke() {
console.log("Hi, I'm an action.");
}
}
为您的 Lightning Web 组件创建一个空模板。
<template> </template>
若要防止在长时间运行的操作中多次并行执行快速操作,请添加内部布尔标志。
的返回类型为 。返回 a 会使方法异步,但返回的方法将被忽略。invoke()voidPromisePromise
此代码使用布尔标志来阻止双重执行,并使用 a 来等待完成。即使返回类型为 ,代码也会异步执行。Promisesleepvoid
import { LightningElement, api } from "lwc";
export default class HeadlessAsync extends LightningElement {
isExecuting = false;
@api async invoke() {
if (this.isExecuting) {
return;
}
this.isExecuting = true;
await this.sleep(2000);
this.isExecuting = false;
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
导航
要导航到 Lightning Experience 中的其他页面、记录或列表,请使用导航服务。
此示例导航到联系人主页。
import { LightningElement, api } from "lwc";
import { NavigationMixin } from "lightning/navigation";
export default class navigateToRecordAction extends NavigationMixin(LightningElement) {
@api invoke() {
this[NavigationMixin.Navigate]({
type: "standard__objectPage",
attributes: {
objectApiName: "Contact",
actionName: "home",
},
});
}
}
import { LightningElement, api } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
export default class DispatchEventAction extends LightningElement {
@api async invoke() {
let event = new ShowToastEvent({
title: "I am a headless action!",
message: "Hi there! Starting...",
});
this.dispatchEvent(event);
await this.sleep(2000);
event = new ShowToastEvent({
title: "I am a headless action!",
message: "All done!",
});
this.dispatchEvent(event);
}
sleep(ms) {
// eslint-disable-next-line @lwc/lwc/no-async-operation
return new Promise((resolve) => setTimeout(resolve, ms));
}
}