测试 Lightning Web 组件

Jest 是一个强大的工具,具有丰富的功能,可用于编写 JavaScript 测试。使用 Jest 为所有 Lightning Web 组件编写单元测试。

在命令行中运行 Jest 测试,或者在 IDE 中(通过一些配置)运行 Jest 测试。Jest 测试不会在浏览器中运行,也不会连接到组织,因此它们运行速度很快。在“监视模式”下运行时,它们会在您编码时为您提供即时反馈。Jest 测试仅适用于 Lightning Web 组件,不适用于 Aura 组件。

将 Jest 测试编写到:

  • 单独测试组件
  • 测试组件的公共 API(属性和方法、事件)@api
  • 测试基本用户交互(点击次数)
  • 验证组件的 DOM 输出
  • 验证事件是否按预期触发

提示

lwc-recipes 存储库中充满了 Jest 测试。在 的 Lightning Web 组件的文件夹中查找 Jest 测试。__tests__force-app/main/default/lwc

安装sfdx-lwc-jest

安装及其依赖项到每个 Salesforce DX 项目中。 仅适用于 Salesforce DX 项目。sfdx-lwc-jestsfdx-lwc-jest

先决条件

在安装之前,请安装 Node.js 和 npm。sfdx-lwc-jest

  • 节点.js此页面列出了 Node.js 的两个版本。我们建议使用“LTS”(长期支持)版本,而不是“当前”版本。
  • npm安装 Node.js 时,npm 也会安装。不过,您可能需要更新 npm,因此请访问 npm 网站以获取说明。

使用 Salesforce CLI 将 Jest 及其依赖项安装到您的项目中

安装 Jest 及其依赖项的最简单方法是运行 Salesforce CLI 命令 sf force lightning lwc test setup。从每个 Salesforce DX 项目的顶级目录运行命令。此命令将创建必要的配置文件并为您安装软件包。sfdx-lwc-jest

手动安装 Jest 及其依赖项

如果您在无法使用 Salesforce CLI 的环境中工作,您可以自行设置测试依赖项。

要安装及其依赖项,请从每个 Salesforce DX 项目的顶级目录运行这些命令一次。sfdx-lwc-jest

npm install
npm install @salesforce/sfdx-lwc-jest --save-dev

默认情况下,SFDX 项目在其文件块中包含这些脚本条目。如果项目文件不包含它们,请添加它们。scriptspackage.json

{
  ...
  "scripts": {
    ...
    "test": "npm run test:unit",
    "test:unit": "sfdx-lwc-jest",
    "test:unit:watch": "sfdx-lwc-jest --watch",
    "test:unit:debug": "sfdx-lwc-jest --debug",
    "test:unit:coverage": "sfdx-lwc-jest --coverage",
    ...
  },
  ...
}

运行 Lightning Web 组件的 Jest 测试

在组件开发过程中频繁或持续运行单元测试。

从 VS Code 运行测试

如果安装适用于 Visual Studio Code 的 Salesforce 扩展,则可以在 VS Code 中运行测试、调试测试和监视 Jest 文件。有关详细信息,请参阅适用于 Visual Studio Code 的 Salesforce 扩展。

在命令行上运行测试

要运行项目的所有测试,请使用 Salesforce CLI 命令 sf force lightning lwc test run from your root folder of your project。否则,请运行在安装 Jest 和 dependencies 时添加到项目文件块的命令。scriptspackage.json

npm run test:unit

在开发过程中持续运行测试

若要在每次保存更改时对单个组件运行所有测试,请转到组件目录并运行带有参数的命令。使用您在安装 Jest 和依赖项时添加到项目文件块的条目。sfdx-lwc-jest--watchscriptspackage.json

npm run test:unit:watch

Jest 会监视所有组件文件的更新,并在每次检测到更改时运行所有相关测试。

在调试模式下运行 Jests 测试

如果要逐步执行测试和应用代码,以找出测试或代码未按预期运行的原因,则在调试模式下运行 Jest 测试非常有用。您可以使用以下工具调试 Jest 测试。

  • VS Code Salesforce 扩展包
  • Chrome 开发者工具
  • VS Code 调试器高级配置

VS Code Salesforce 扩展包提供了最简单、最直接的选项,而 Chrome DevTools 则迎合了经验丰富的 Web 开发人员的需求。此外,VS Code 调试器的高级配置使你能够使用不同的调试器和调试方案。高级配置为调试 Jest 测试提供了最灵活的选项。

有关更多信息,请参阅调试 Lightning Web 组件的 Jest 测试。

高级 Jest 配置

sfdx-lwc-jest配置为运行 Jest 测试,无需任何其他更改。但是,如果您是 Jest 的高级用户,请查看 Jest 的其他一些配置选项。请参见 github.com/salesforce/sfdx-lwc-jest#overriding-jest-config

重要

如果你的 Jest 测试执行缓慢,并且它们有来自不同文件夹的依赖项,请提供映射以加快解析速度。请参阅 lwc-recipes 存储库中的 。moduleNameMapper

调试 Lightning Web 组件的 Jest 测试

VS Code 提供了一些工具来帮助你有效地调试 Jest 测试。根据您的测试要求,使用 Salesforce 扩展包、Chrome DevTools 或 VS Code 调试器高级配置。

使用 Salesforce 扩展包调试测试

适用于 Visual Studio Code 的 Salesforce 扩展提供了一个 LWC 测试侧边栏,供您轻松运行测试。可以运行一个测试用例、一个文件中的所有测试用例或项目的所有测试。有关详细信息,请参阅 LWC 测试侧栏中的功能概述。

若要调试测试,请在测试中添加断点。

例如,如果要确保正确调度事件,请单击包含方法的行号 (1)。您还可以在组件的 JavaScript 文件中的事件处理程序上添加断点,以观察事件处理程序的触发时间。dispatchEvent()

添加断点后,单击“调试测试”(2)。此链接运行以下命令:。node --inspect-brk node_modules/.bin/jest --runInBand

提示

请参阅 lwc-recipes 存储库。helloConditionalRendering.test.js

在“运行”视图中显示与运行和调试相关的信息。

若要打开“运行”视图,请单击“运行和调试”(1),您可以在其中查看表达式 (2),并使用调试工具栏 (3) 单步执行测试。在调试控制台 (4) 中,可以在测试执行时检查元素。

单击调试工具栏 (3) 上的“继续”以单步执行断点。如果未收到错误,则测试将成功完成。在 VS Code 终端中查看任何测试执行输出。

调试 Jest Salesforce 扩展

https://youtube.com/watch?v=OOGn0JLabS0

提示

有关更多调试技术,请参阅从文件内运行、调试或观看 Jest 测试。

使用 Chrome DevTools 调试测试

虽然 Salesforce 扩展包使您能够从 VS Code 中调试 Jest 测试,但 Chrome DevTools 为您提供了用于 Web 开发的全面诊断功能。

若要在调试模式下运行项目中的所有测试,请在 VS Code 终端中输入此命令。

npm run test:unit:debug

此命令调用 ,然后运行 。sfdx-lwc-jest --debugnode --inspect-brk node_modules/.bin/jest --runInBand

注意

我们建议您使用该命令,因为该命令已解析为节点依赖项,并且无法在命令行上访问。npm run test:unit:debugsfdx-lwc-jest

若要在调试模式下运行单个测试,请输入此命令,其中要调试的测试的名称。testName

npm run test:unit:debug -- testName

接下来,打开 Chrome 浏览器并转到 。“远程目标”部分列出了在调试模式下在系统中运行的所有节点进程。chrome://inspect

若要打开“DevTools”窗口,请单击“远程目标”部分中列出的“Jest 测试”下的“检查”链接。

使用“DevTools 源”面板可以调试测试。首先,在 VS Code 的测试代码中添加一条语句。debugger

注意

Chrome 检查器不会单步执行你在上一部分的 VS Code 中指定的断点。请改用测试中的语句。debugger

若要恢复测试执行,请单击 DevTools 中的“恢复脚本执行 (Resume icon)”按钮。测试将显示您的测试代码,并在您添加的语句处停止,如已编译代码的第 36 行所示。然后,可以在“源”面板中添加断点,如此屏幕截图中的第 37 行所示。debugger

提示

有关使用 Chrome DevTools 的更多调试技术,请参阅调试 JavaScript。

如果需要更好地控制如何在调试模式下运行 Jest 测试,请考虑使用 VS Code 高级配置。

使用 Chrome 开发者工具调试 Jest 测试

https://youtube.com/watch?v=TDHCrLAn33E

使用 VS Code 高级配置调试 Jest 测试

VS Code 允许你配置在调试模式下运行 Jest 测试的方式。

要使用高级配置,请执行以下操作:

  1. 生成启动配置文件。
    1. 在“运行”视图中,单击“创建 launch.json 文件”链接。从“运行和调试”选项卡生成 launch.json 文件
    2. 在显示的下拉列表中,选择“Node.js”,这将为您创建一个文件。将 的内容替换为 sfdx-lwc-jest 存储库的 Visual Studio Code 中的调试中所示的配置。launch.jsonlaunch.json注意Mac 和 Windows 用户的配置不同。按照 sfdx-lwc-jest 存储库中的说明查找操作系统的配置。若要为不同的调试器和调试方案自定义启动配置,请使用 VS Code 的 launch.json 属性。
  2. 在 Salesforce DX 项目的根目录下添加一个 Jest 配置文件。在此文件中,包括 sfdx-lwc-jest 存储库中覆盖 Jest Config 中提供的配置代码。配置代码如下所示。jest.config.jsconst { jestConfig } = require("@salesforce/sfdx-lwc-jest/config"); module.exports = { ...jestConfig, // add any custom configurations here };
  3. 在测试代码和组件的 JavaScript 文件中添加语句。debugger注意使用 VS Code 中的高级配置进行调试时,不支持添加断点。添加断点的行号与编译文件中的行号不匹配。请改用该语句。debugger
  4. 启动配置文件。转到“运行”视图。选择 Debug Jest Tests 配置,然后单击 Start Debugging (“开始调试”图标)。默认情况下,此命令运行项目中的所有测试,并在测试代码和组件的 JavaScript 文件中添加的所有调试器语句中停止。可以在 VS Code 终端中查看执行输出,并使用 VS Code 中的调试功能,例如使用调试控制台检查变量。

使用 VSCode 调试器高级配置调试 Jest 测试

https://youtube.com/watch?v=x3EbNOiczm4

提示

有关解决 Jest 问题的信息,请参阅 jestjs.io/docs/en/troubleshooting

为 Lightning Web 组件编写 Jest 测试

在本地 JavaScript 文件中编写组件测试。将它们与组件本身一起提交到版本控制中。Jest 测试不会保存到 Salesforce。

Jest 测试的编写、保存和运行方式与为 Lightning 测试服务编写的 Jasmine 或 Mocha 测试不同。Jest 测试仅是本地测试,并且独立于 Salesforce 保存和运行。

您可以使用 Salesforce CLI 命令 sf force lightning lwc test create 在目录中创建测试目录和样板测试文件。以下命令创建用于测试 Lightning Web 组件的测试目录和文件。myButton

sf force lightning lwc test create -f force-app/main/default/lwc/myButton/myButton.js

组件文件夹结构

使用 Salesforce CLI 命令后,您会看到在组件的捆绑包目录的顶层命名的文件夹,例如 .否则,请自行创建文件夹。将此组件的所有测试保存在文件夹中。通过将文件夹提交到版本控制,与其他团队成员或系统共享测试。create__tests__force-app/main/default/lwc/myButton/__tests____tests____tests__

更新 .forceignore

要确保文件夹及其内容永远不会保存到 Salesforce,请将此 glob 模式添加到每个项目的文件中。Salesforce CLI 命令 sf force lightning lwc test setup 会为您执行此任务。__tests__.forceignore

**/__tests__/**

此模式可确保推送、拉取或转换代码和元数据的 Salesforce DX 命令忽略文件夹及其内容。__tests__

测试文件命名约定

Jest 在目录中运行 JavaScript 文件。测试文件的名称必须以 结尾,我们建议测试以 结尾。可以使用一个包含所有组件测试的测试文件,也可以使用多个文件来组织相关测试。测试文件可以放在子文件夹中。__tests__.js.test.js

编写基本测试

要成为一名有成就的测试人员,请学习如何使用 Jest。特别是,学习 Jest 提供的许多匹配器的语法。我们在这里不介绍 Jest 的一般用法,因为 Jest 文档非常出色。我们专注于将 Jest 与 Lightning Web 组件一起使用的细节。

Lightning Web 组件的 Jest 测试应该单独测试单个组件的行为,对外部组件或服务的依赖性最小。

让我们看一下,这是对 lwc-recipes 存储库中 Lightning Web 组件的测试。hello.test.jshello

// hello.test.js
import { createElement } from "lwc";
import Hello from "c/hello";

describe("c-hello", () => {
  afterEach(() => {
    // The jsdom instance is shared across test cases in a single file so reset the DOM
    while (document.body.firstChild) {
      document.body.removeChild(document.body.firstChild);
    }
  });

  it("displays greeting", () => {
    // Create element
    const element = createElement("c-hello", {
      is: Hello,
    });
    document.body.appendChild(element);

    // Verify displayed greeting
    const div = element.shadowRoot.querySelector("div");
    expect(div.textContent).toBe("Hello, World!");
  });
});

让我们演练一下代码,并了解测试文件的每个部分。所有测试都必须使用此结构。

进口

首先,测试导入方法。此方法仅在测试中可用。代码还必须导入要测试的组件,在本例中为 .稍后使用这些导入来创建受测组件。createElementc/hello

import { createElement } from "lwc";
import Hello from "c/hello";

描述块

模块定义测试套件。测试套件包含一个或多个测试,从功能角度来看,这些测试属于一起。describe

describe('c-hello', () => {
  ...
});

我们建议使用一个顶级块,其描述与组件名称匹配。仅在必要时添加更多对功能进行分组的块。describedescribe

对于 ,单个就足够了。对于更复杂的组件,使用多个块将事物分组为错误场景、空输入、有线数据、常规数据等类别可能是有意义的。hello.test.jsdescribedescribe

在测试之间清理

Jest afterEach() 方法在测试结束时重置 DOM。

由于测试运行时浏览器没有运行,因此 Jest 用来提供一个行为与浏览器的 DOM 或 .Jest 依赖于 ,这是一个 Node.js 项目,因此在项目安装过程中下载的方式与 Jest 本身相同。jsdomdocumentjsdomjsdomsfdx-lwc-jest

每个测试文件共享一个 的实例,并且文件内的测试之间不会重置更改。因此,最佳做法是在测试之间进行清理,以便测试的输出不会影响任何其他测试。jsdom

afterEach(() => {
  // The jsdom instance is shared across test cases in a single file so reset the DOM
  while (document.body.firstChild) {
    document.body.removeChild(document.body.firstChild);
  }
});

Jest 还具有其他可用于执行设置和清理任务的方法。请参见 jestjs.io/docs/en/setup-teardown

IT(或测试)块

注意

it是 test 的别名。使用任何可以让您准确描述预期行为的词。

块描述单个测试。测试表示要测试的单个功能单元。编写 以描述该函数的预期行为。例如,该组件显示“Hello, World!”,因此该块会测试 hello 组件是否显示问候语。itithelloit

it('displays greeting', () => {
    ...
});

创建测试组件

该测试使用导入的方法创建要测试的组件的实例,在本例中为 .createElementc-hello

const element = createElement("c-hello", {
  is: Hello,
});

将测试组件添加到 DOM 中

然后,测试调用以将组件添加到测试的 版本 中。appendChilddocument

调用将组件插入到 DOM 和生命周期钩子中,然后被调用。appendChild()connectedCallback()renderedCallback()

document.body.appendChild(element);

下一步是使用标准的 DOM 查询方法在 DOM 中搜索元素。用作查询的父级。这是一个仅限测试的 API,可让您查看阴影边界以检查组件的阴影树。它等效于 .element.shadowRootthis.template

const div = element.shadowRoot.querySelector("div");

使用断言

最后,该语句是对成功条件的断言:元素的文本为“Hello, World!”expect

const div = element.shadowRoot.querySelector("div");
expect(div.textContent).toBe("Hello, World!");

Jest 支持许多匹配器,例如 和,这使得检查值是否满足条件变得容易。请参见 jestjs.io/docs/en/expecttoBetoMatchObject

测试异步 DOM 更新

当 Lightning Web 组件的状态发生变化时,DOM 会异步更新。若要确保测试在评估结果之前等待更新完成,请返回已解析的 Promise。将测试代码的其余部分链接到解析的 Promise。Jest 等待 Promise 链完成,然后再结束测试。如果 Promise 以拒绝状态结束,则 Jest 无法通过测试。

test("element does not have slds-icon class when bare", () => {
  const element = createElement("one-primitive-icon", { is: PrimitiveIcon });
  document.body.appendChild(element);
  // Property value is assigned after the component is inserted into the DOM
  element.variant = "bare";

  // Use a promise to wait for asynchronous changes to the DOM
  return Promise.resolve().then(() => {
    expect(element.classList).not.toContain("slds-icon");
  });
});

调用将组件插入到 DOM 和生命周期钩子中,然后被调用。然后,该示例在调用后设置元素值,这类似于将组件插入 DOM 后由另一个方法或用户交互设置属性的情况。在这些情况下,请使用 promise 等待异步 DOM 更新。有关组件生命周期和呈现的更多信息,请参见生命周期流。appendChild()connectedCallback()renderedCallback()appendChild()

如果在调用之前设置了该属性,则会同步呈现组件。在调用之前设置该属性时,无需等待异步更新或返回 promise。appendChild()appendChild()

为使用 Wire Service 的 Lightning Web 组件编写 Jest 测试

组件使用线路服务从 Salesforce 获取数据。若要测试这些组件如何处理来自线路服务的数据和错误,请使用测试实用程序。@salesforce/sfdx-lwc-jest

测试使用的输入不应依赖于外部代码或数据,您必须对其进行完全控制。从中导入测试实用程序 API 以模拟数据,以便测试不依赖于远程调用或服务器延迟等不可预测因素。sfdx-lwc-jest

该实用程序有三个适配器用于模拟线路服务数据:通用线路适配器、Lightning 数据服务 (LDS) 线路适配器和 Apex 线路适配器。sfdx-lwc-jest

  • 调用 API 时,通用适配器会按需发出数据。它不包含有关数据本身的任何额外信息。emit()
  • LDS 适配器模拟 Lightning 数据服务行为,并包含有关数据属性的信息。
  • Apex 线路适配器模拟对 Apex 方法的调用,并包含任何错误状态。

注意

如果您未使用该实用程序来使用 Salesforce DX,则可以使用测试实用程序导入适配器。但是,我们建议使用集成开发体验。sfdx-lwc-jest@salesforce/wire-service-jest-utilsfdx-lwc-jest

若要控制测试,请创建一个 JSON 文件来定义组件所需的数据,而不是从 Salesforce 获取数据。

若要使用线路服务测试实用程序,请按照以下高级步骤操作。

  1. 在组件包中,创建一个名为 的文件夹和一个名为 的 JavaScript 类。最佳做法是以组件命名文件,后跟 .__tests__componentName.test.js.test.js
  2. 在文件夹中,创建一个文件夹和一个名为 .__tests__data_wireAdapter_.json
    1. 在 JSON 文件中,模拟电线适配器发出的数据。
    2. 如果有线适配器是 LDS 有线适配器,请使用访问有线适配器所基于的 UI API 的 REST 客户端获取数据快照。这种方法比手动编写 JSON 更准确。
  3. 在文件中:componentName.test.js
    1. 导入被测元件及其电线适配器。测试必须引用与被测组件相同的电线适配器。
    2. 从 JSON 文件导入模拟数据。
    3. 发出模拟数据。
    4. 验证组件是否收到了模拟数据。

被测组件

我们的示例组件是产品卡组件。

产品卡组件显示产品及其名称。

<!-- productCard.html -->
<template>
  <div class="content">
    <template lwc:if={product}>         
        <div class="name">         
          <div>Name:</div>
          <div>{name}</div>
        </div>
    </template>
  </div>
</template>

在组件的 JavaScript 文件中,修饰器指示线路服务使用线路适配器来设置记录数据。它装饰函数,该函数接收具有错误或数据属性的对象。@wiregetRecordwiredRecord

// productCard.js
import { LightningElement, wire } from "lwc";

// Wire adapter to load records.
import { getRecord } from "lightning/uiRecordApi";

export default class ProductCard extends LightningElement {
  // Id of Product__c to display.
  recordId;

  // Product__c to display
  product;

  // Product__c field values to display
  name = "";

  @wire(getRecord, { recordId: "$recordId", fields: ["Product.Name"] })
  wiredRecord({ data }) {
    if (data) {
      this.product = data;
      this.name = data.fields.Name.value;
    }
  }
}

提示

lwc-recipes 存储库提供了使用有线服务的几个组件的示例,其中包括 Jest 测试。

模拟数据

在文件夹中,创建一个名为 的文件夹。在文件夹中,创建一个名为 的文件,该文件与电线适配器同名。定义组件期望从服务器获得的数据。您可以自己编写 JSON,但这可能会变得困难且容易出错。最佳做法是使用访问 UI API 的 REST 客户端获取数据快照。例如,此数据是来自 的响应,该响应是支持电线适配器的资源。__tests__datadatagetRecord.json/ui-api/records/{recordId}getRecord

我们的模拟数据仅定义记录中的字段。在实际测试中,模拟组件所需的所有数据。Name

{
  "fields": {
    "Name": {
      "value": "DYNAMO X1"
    }
  }
}

创建 JavaScript 测试

单元测试检查产品卡是否显示产品名称。

测试必须导入被测组件中使用的电线适配器。在这里,这是模块中的电线适配器。测试还必须导入模拟数据以通过电线适配器发送。getRecordlightning/uiRecordApi

该测试创建组件并将其附加到 DOM。仅当组件连接到 DOM 时,组件才会接收有关数据的更新。组件连接后,将模拟数据传递给电线适配器上的函数。emit

发出模拟数据后,if 或 change 组件将重新呈现。解析 promise 以确保测试代码在 DOM 更新为新数据后运行。该代码验证模拟数据中的产品名称字段是否在 DOM 中正确输出。productname

// productCard.test.js
import { createElement } from "lwc";
import ProductCard from "c/productCard";
import { getRecord } from "lightning/uiRecordApi";

// Import mock data to send through the wire adapter.
const mockGetRecord = require("./data/getRecord.json");

test("displays product name field", () => {
  const element = createElement("c-product_filter", { is: ProductCard });
  document.body.appendChild(element);

  // Emit mock record into the wired field
  getRecord.emit(mockGetRecord);

  // Resolve a promise to wait for a rerender of the new content.
  return Promise.resolve().then(() => {
    const content = element.shadowRoot.querySelector(".content");
    const nameField = mockGetRecord.fields.Name.value;
    expect(content.textContent).toBe(`Name:${nameField}`);
  });
});

注意

在 Spring ’21 及更早版本中,您必须注册正在测试的电线适配器。该代码仍然有效,但不建议这样做。

DOM 检查测试可能会发生变化

Lightning Experience 中 HTML、CSS 和 DOM 的内容和结构可能随时更改,不能被视为稳定的 API。使用 Selenium WebDriver 等工具进入组件内部的 UI 测试需要持续维护。

Salesforce 从不保证向后兼容 HTML、CSS 或 DOM。我们指出,随着 Lightning Experience 随着现代 Web 标准的发展而不断变化,这些测试的脆弱性。我们了解您从自动化 UI 测试中获得的价值,以及由此给您带来的维护负担。

Lightning Web 组件基于 Web 组件标准。该标准包括 Shadow DOM,它对其他组件隐藏组件的标记、样式和行为。这种封装给 UI 测试带来了挑战,尤其是依赖于全局搜索 DOM 或进入自定义元素内部的测试。

该属性封装元素的 DOM 子树。这在 DOM 中表示为 一个。 这个 DOM 子树中的元素不能通过传统的 DOM 查询方法获得。由 Lightning Web 组件呈现的元素包含此新属性,并且这些元素在正常的 DOM 查询中是隐藏的。shadowRootshadowRootDocumentFragmentshadowRoot

我们建议使用 Jest 对单个 Lightning Web 组件进行单元测试。

仅将 Selenium WebDriver 等 UI 测试工具用于端到端测试。

开玩笑测试

要为 Lightning Web 组件编写单元测试,请使用 sfdx-lwc-jest。

在 Jest 测试上下文中,代码可以使用被测元素的属性来访问影子树。该属性封装元素的影子树。shadowRootshadowRoot

此代码在“示例”部分访问组件的影子树。<div><lightning-lwc-parent>

const element = createElement("c-lightning-lwc-parent", { is: LightningLwcParent });
document.body.appendChild(element);
const div = element.shadowRoot.querySelector(".in-the-shadow");

Selenium WebDriver 测试

对于端到端 UI 测试,请调整现有测试以使用 Shadow DOM。调整测试因工具而异,策略也在迅速发展。本文是 Selenium WebDriver 的一个很好的例子。

正如本文所讨论的,全局查询通过失败。要在 Lightning Web 组件的影子树中查找元素,请在客户端上执行 JavaScript 以查询组件的属性。WebDriver.findElement()shadowRoot

注意

本文有一个屏幕截图,显示了 Chrome 开发者工具中的 DOM 元素。屏幕截图显示了一个文档片段,它是组件影子树的顶部节点。如果您在 Chrome 开发者工具中查看 Lightning Web 组件,则看不到 因为 LWC 使用影子 DOM polyfill。Salesforce 支持某些未实现 Shadow DOM Web 标准的浏览器。polyfill 在这些浏览器中提供了一个影子 DOM。要在页面上查找 Lightning Web 组件,请查找包含连字符的元素名称。选择元素并在控制台中运行。Lightning Web 组件返回 .#shadow-root#shadow-root$0.shadowRoot#document-fragment

Jest 测试模式和模拟依赖关系

在使用 Jest 进行测试时,请遵循这些模式和做法来隔离行为并最大限度地提高单元测试的效率。

测试属性更改

让我们从一个简单的属性更改开始。属性更改时的组件重新渲染是异步的,因此向 DOM 添加某些内容的顺序并不总是可预测的。我们建议您在检查预期行为之前,等待值更改反映在 DOM 中。一种技术使用语句在页面元素更改后检查值,如下所示:Promise.resolve()

  1. 将组件添加到 DOM。
  2. 更改属性值。
  3. 等待组件通过返回值重新呈现。Promise.resolve()
it("Renders with Hello Matt", () => {
  const element = createElement("c-hello-component", {
    is: HelloComponent,
  });
  document.body.appendChild(element);

  element.person = "Matt";

  return Promise.resolve().then(() => {
    const pTag = element.shadowRoot.querySelector("p");
    expect(pTag.textContent).toEqual("Hello, Matt!");
  });
});

提示

有关更多信息,请参阅 Matt Goldspink 在 Vlocity 撰写的博客文章 Testing Lightning Web Components。

使用属性测试组件

为了扩展我们的示例,让我们添加一个属性。属性允许您在测试中更改一个值,以查看更改的呈现方式。使用语句在调用之前设置属性,例如:Object.assign()appendChild

Object.assign(element, attributes);
document.body.appendChild(element);

例如,让我们将初始测试中的背景颜色设置为红色:

it("Renders with Hello Matt", () => {
  const element = createElement("c-hello-component", {
    is: HelloComponent,
  });
  Object.assign(component, { backgroundColor: "red" });
  document.body.appendChild(element);

  element.person = "Matt";

  return Promise.resolve().then(() => {
    const pTag = element.shadowRoot.querySelector("p");
    expect(pTag.textContent).toEqual("Hello, Matt!");
  });
});

嘲笑

单元测试可能涉及的不仅仅是对简单 UI 元素的更新。某些代码依赖于某些依赖项的行为,例如导入的模块、基本 Lightning 组件和事件处理程序。但是,您希望您的代码处于一致的环境中,不受服务器调用、数据库请求或远程访问 API 的可变行为和计时的影响。以下部分包括有关单元测试的这些依赖项的模拟行为的指南。模拟是一种常见的测试做法,用于隔离正在测试的代码的行为。

基本 Lightning 组件

Salesforce 在 sfdx-lwc-jest 存储库中提供了模拟组件,您可以在 lightning-stubs 目录中找到这些组件的源代码。将这些模拟组件用于包含基本 Lightning 组件的测试。模拟组件与实际组件的 API 匹配,但不具备所有功能,因此它们可以作为测试的良好资源。即使这些模拟组件不会触发任何事件,您仍然可以调用其事件处理程序。

例如,查看 lwc-recipes 存储库中的 miscToastNotification.js 示例。为了模拟用户输入,常量引用了 sfdx-lwc-jest 提供的模拟元素。我们仍然可以在 DOM 中查询它,并从中调度一个事件来调用我们连接到它的处理程序。我们使用一个模拟组件来保持对输入值的控制,因为我们只想测试通知的行为。inputTitleEl<lightning-input>change

// Select input field for simulating user input
const inputMessageEl = element.shadowRoot.querySelector('lightning-input[data-id="messageInput"]');
inputMessageEl.value = TOAST_MESSAGE;
inputMessageEl.dispatchEvent(new CustomEvent("change"));

在使用我们的模拟组件时,请记住以下几点。

  • 我们建议您的测试不要依赖于插槽的呈现顺序。例如,假设有两个命名槽:和 。如果存在预期内容,则即使模拟(或真实)组件交换了这些插槽的呈现顺序,测试也会通过。actionstodos
  • 基本 Lightning 组件具有一些属性,这些属性不会反映为 DOM 中的属性。例如,您可以设置属性 ,该属性用于确定要用于按钮的 SLDS 类,而不是呈现的值。设计测试用例以考虑此行为,并且不要假定所有属性都反映为属性。<lightning-button>iconPosition
  • 这些模拟不会触发任何事件,但您可以调用它们。dispatchEvent()

事件处理程序

查看相同的 miscToastNotification.js 示例,也可以看到一个模拟事件处理程序。此测试定义多个常量值,然后触发事件,将常量插入元素中。ShowToastEventNamejest.fn()lightning-input

const TOAST_TITLE = "The Title";
const TOAST_MESSAGE = "The Message";
const TOAST_VARIANT = "warning";

// Create initial element
const element = createElement("c-misc-toast-notification", {
  is: MiscToastNotification,
});
document.body.appendChild(element);

// Mock handler for toast event
const handler = jest.fn();
// Add event listener to catch toast event
element.addEventListener(ShowToastEventName, handler);

在测试结束时,验证事件处理程序是否按预期调用,以及是否使用正确的参数。

return Promise.resolve().then(() => {
  // Check if toast event has been fired
  expect(handler).toHaveBeenCalled();
  expect(handler.mock.calls[0][0].detail.title).toBe(TOAST_TITLE);
  expect(handler.mock.calls[0][0].detail.message).toBe(TOAST_MESSAGE);
  expect(handler.mock.calls[0][0].detail.variant).toBe(TOAST_VARIANT);
});

模块导入

若要创建对模拟组件的引用以更好地控制组件行为,请在文件中添加 moduleNameMapper 设置。要查看示例,请查看 lwc-recipes 存储库中的 jest.config.js 如何引用一些带有模块名称的模拟组件。jest.config.js

const { jestConfig } = require("@salesforce/sfdx-lwc-jest/config");
module.exports = {
  ...jestConfig,
  moduleNameMapper: {
    "^@salesforce/apex$": "<rootDir>/force-app/test/jest-mocks/apex",
    "^lightning/navigation$": "<rootDir>/force-app/test/jest-mocks/lightning/navigation",
    "^lightning/platformShowToastEvent$":
      "<rootDir>/force-app/test/jest-mocks/lightning/platformShowToastEvent",
    "^lightning/uiRecordApi$": "<rootDir>/force-app/test/jest-mocks/lightning/uiRecordApi",
  },
};

现在,让我们看看如何在 lwc-recipes 存储库的 miscToastNotification.test.js 中使用此配置。它有一个声明:import

import { ShowToastEventName } from "lightning/platformShowToastEvent";

如果没有该条目,此语句将解析为存根 https://github.com/salesforce/sfdx-lwc-jest/blob/master/src/lightning-stubs/platformShowToastEvent/platformShowToastEvent.js。moduleNameMapperimport

使用该条目时,此语句解析为 jest-mocks 自定义存根 https://github.com/trailheadapps/lwc-recipes/blob/master/force-app/test/jest-mocks/lightning/platformShowToastEvent.js。模拟存根具有向事件对象添加其他属性的自定义逻辑。moduleNameMapperimport

注意

如果使用自定义选项覆盖缺省文件,请将这些值与 中定义的值合并。jest.config.jssetupFilesAfterEnv@salesforce/sfdx-lwc-jest/config

@salesforce范围的导入

在测试环境中,组件可能无权访问生产架构。导入对命名空间的引用时,请在测试期间将返回值模拟为占位符。

在 Jest 测试中,我们使用 jest-transformer 将 import 语句转换为变量声明。该值设置为标签路径。默认情况下,分配的字符串值为 。您可以使用为导入提供自己的值。此示例返回字符串而不是 。@salesforce/labelmyImportc.specialLabeljest.mock()value set in testc.specialLabel

import myImport from "@salesforce/label/c.specialLabel";

jest.mock(
  "@salesforce/label/c.specialLabel",
  () => {
    return { default: "value set in test" };
  },
  { virtual: true },
);

寻找更多示例?

请参阅 lwc-recipes 存储库的 lwc 目录。许多食谱都有一个目录,其中包含注释的 jest tests。__tests__

提高性能

启用 CDN 和安全浏览器缓存以提高应用程序性能。

注意

每天第一次加载组件时,加载速度会变慢,因为该组件未缓存。在后续加载时,组件的加载和显示速度更快。

启用安全浏览器缓存

在浏览器中启用安全数据缓存,通过避免与服务器的额外往返来提高页面重新加载性能。

默认情况下,此设置处于选中状态。

注意

禁用安全和持久的浏览器缓存会对 Lightning Experience 的性能产生重大负面影响。仅在这些情况下禁用。

  • 公司的策略不允许浏览器缓存,即使数据已加密也是如此。
  • 在沙盒或 Developer Edition 中进行开发时,您希望在不清空安全缓存的情况下查看任何代码更改的效果。
  1. 在“设置”中,输入“快速查找”框,然后选择“会话设置”。Session
  2. 选中“启用安全且持久的浏览器缓存以提高性能”复选框。
  3. 点击保存

使 CDN 能够更快地加载应用程序

通过启用 Akamai 的内容分发网络 (CDN) 为 Lightning 组件框架提供静态内容,更快地加载 Lightning Experience 和其他应用程序。CDN 通常会加快页面加载时间,但它也会更改提供文件的源域。如果您的公司对 Salesforce 提供的内容有 IP 范围限制,请在启用此设置之前进行全面测试。

CDN 通过将缓存版本存储在多个地理位置来缩短静态内容的加载时间。此设置为 Lightning 组件框架中的静态 JavaScript 和 CSS 启用 CDN 交付。它不会在 CDN 中分发您的 Salesforce 数据或元数据。

默认情况下,对于在 Winter ’19 版本之前创建的组织,此设置处于禁用状态,默认情况下,对于新组织以及所有新的和现有的 Experience Builder 站点,此设置处于禁用状态。适用于 Experience Builder 站点的 Lightning CDN 无法关闭且不可配置。

  1. 在“设置”中,输入“快速查找”框,然后选择“会话设置”。Session
  2. 选中“为 Lightning 组件框架启用内容分发网络 (CDN)”复选框。
  3. 点击保存。如果您遇到任何问题,请询问您的网络管理员贵公司的防火墙是否阻止了任何 Akamai CDN 内容。确保将其添加到贵公司运营的任何允许列表或防火墙中。您可以 ping 操作,但不能直接浏览到 位于 的根 URL。https://static.lightning.force.comstatic.lightning.force.comhttps://static.lightning.force.com重要不要使用 IP 地址进行网络过滤,因为这可能会导致 的连接问题。的 IP 地址是动态的,不会在 Salesforce 的允许的 IP 地址列表中进行维护。https://static.lightning.force.comhttps://static.lightning.force.com

调试 Lightning Web 组件

Lightning Web 组件使用标准 HTML 和 JavaScript 构建,在桌面上,它们在各种受支持的浏览器中运行。您可以使用标准浏览器和 JavaScript 调试工具(如 Chrome DevTools)在开发过程中调试组件。若要查看特定于移动设备的功能,请使用移动设备或虚拟设备内部版本。

在开发过程中运行和调试组件的最简单方法是创建一个 Lightning 页面并将您的组件添加到其中。然后在您喜欢的浏览器中加载 Lightning 页面,并使用您喜欢的检查和调试工具。LWC 调试针对 Chrome DevTools 进行了优化。

注意

此内容改编自 Salesforce 首席开发人员布道师 René Winklemeyer 的博客文章调试您的 Lightning Web 组件

Lightning 组件的执行模式

Lightning 组件框架以以下两种模式之一执行:生产模式和调试模式。

让我们看一下执行模式之间的差异。

生产模式

默认情况下,框架在生产模式下运行。此模式针对性能进行了优化。

在生产模式下,JavaScript 代码经过优化和“缩小”,以将代码的大小减小到尽可能少的字节。生产模式删除了换行符、空格、制表符和代码注释,并缩短了函数和变量的名称。由于此过程,提供给浏览器的 JavaScript 代码被模糊处理。

注意

缩小是性能优化,而不是知识产权保护。缩小的代码很难阅读,但未加密或以其他方式阻止查看。

在生产模式下可见的代理对象

生产模式还对某些事情使用 JavaScript 代理,例如通过装饰器 、 和 提供的数据。和修饰属性被视为只读属性。通过使用 JavaScript 代理,框架可以确保无法修改这些属性。对于修饰的属性,框架使用代理来观察数据突变,以便它可以对更改做出反应。在生产模式下进行调试时,你看到的是代理对象,而不是你感兴趣的对象。@api@wire@track@api@wire@track

Lightning Locker 和 Lightning Web Security 在标准 Web API 上使用代理对象来防止对 DOM 中的全局对象进行更改。

生产模式调试

您可以使用 Chrome DevTools 中的“漂亮打印”选项在生产模式下获得最少的代码格式。单击“源”面板底部的漂亮打印图标以打开应用了格式的新选项卡。{}

由于变量和函数的名称已更改,代码仍然不完全可读,但对于第一次检查来说是很好的。您可以在 Chrome DevTools 中设置断点、检查值以及使用调试器。

以下是默认情况下在生产模式下看到的内容,使用 lwc-recipes 中的示例代码。在此示例中,第 1 行延伸超过 1200 个字符。

以下是选择“漂亮的打印件”后在生产模式下看到的内容。

调试模式

在调试模式下,JavaScript 代码更易于阅读和调试。在 DevTools 中看到的 JavaScript 源代码与未编译的源代码类似。调试模式还为某些警告和错误添加了更详细的输出。

组件代码在生产模式和调试模式下编译。在调试模式下,编译的 JavaScript 代码不会优化或缩小。LWC 编译器可以生成支持更高级调试功能的信息。

为用户帐户启用调试模式后,您会看到这些更改。

  • 顶部会出现一个横幅,提醒您调试模式已打开,并且会减慢速度。
  • “体验页面时间 (EPT)”指标显示在页眉中。它以绿色、橙色或红色显示,以指示页面加载时间的运行状况。
  • 页眉中的存储指标显示页面存储的千字节数据,以指示内存使用情况和缓存。该指标以绿色、橙色或红色进行类似的颜色编码。

我们在生产模式下看到的相同的 lwc-recipes 示例代码,在启用调试模式时未缩小时,看起来不那么神秘。它更具可读性,并显示函数和变量的名称。

在 Salesforce 中启用调试模式

启用调试模式,以便更轻松地调试 JavaScript 代码。仅对主动调试 JavaScript 的用户启用调试模式。对于启用了调试模式的用户,Salesforce 速度较慢。

要为组织中的用户启用调试模式,请执行以下操作:

  1. 在 Salesforce 中,从“设置”中输入“快速查找”框,然后选择“调试模式用户”。Debug Mode启用了调试模式的用户在“调试模式”列中有一个复选标记。
  2. 在用户列表中,找到需要启用调试模式的任何用户。如有必要,请使用标准列表视图控件来筛选组织的用户。
  3. 选中要为其启用调试模式的用户旁边的复选框。
  4. 单击启用

提示

如果在 JavaScript 文件中只看到几行代码,则未启用调试模式。如果启用调试模式无法重置代码编辑器中的代码,请执行硬重新加载。打开 DevTools 后,右键单击浏览器的“重新加载”按钮,然后单击“硬重新加载”。

若要为用户禁用调试模式,请按照上述步骤操作,然后单击“禁用”而不是“启用”。

在开发过程中禁用缓存

在沙盒或 Developer Edition 组织中禁用安全和持久的浏览器缓存设置,以便在不清空缓存的情况下查看任何代码更改的效果。

缓存设置通过避免与服务器的额外往返来提高页面重新加载性能。

警告

禁用安全和持久的浏览器缓存会对 Lightning Experience 的性能产生重大负面影响。始终在生产组织中启用该设置。

  1. 在“设置”中,输入“快速查找”框,然后选择“会话设置”。Session
  2. 取消选中“启用安全且持久的浏览器缓存以提高性能”复选框。
  3. 点击保存

禁用浏览器缓存设置后,您可以重新加载页面以测试代码更改,而无需清除缓存。我们建议您在调试代码后重新启用浏览器缓存设置。

使用 Chrome DevTools 进行调试

要调试 Lightning Web 组件代码,请使用 Chrome DevTools。

Google Chrome 包含一整套出色的 Web 开发工具,即 Chrome DevTools。这些工具非常适合调试 Lightning Web 组件。

首先,加载可以运行 Lightning 组件的最简单页面。然后打开 DevTools。

  • 在 Windows 和 Linux 上,在 Google Chrome 浏览器中按下 Control-Shift-I。
  • 在 Mac 上,按下 Option-Command-I。
  • 在任何平台上,按 F12 或在页面中单击鼠标右键,然后选择“检查”。

若要快速查找失败的代码行,请在“源”面板中启用“DevTools 调试器面板中的”暂停所有异常“选项,然后再运行代码。

当您启用异常暂停时,浏览器会在由 Salesforce 代码、其他库代码和组件代码引起的异常时停止。组件引发的异常可能会在框架代码中被捕获。

要了解有关在 Google Chrome 上调试 JavaScript 的更多信息,请参阅 Google Chrome DevTools 网站。

请查看 Trailhead 上的 Lightning Web 组件故障排除,了解将 Chrome DevTools 与 Lightning Web 组件结合使用的分步说明。

在“源”面板中查找代码

在 Chrome DevTools 的“源”面板中,在文件夹的“页面”窗格中找到您的 Lightning Web 组件代码。在这里,您可以看到默认命名空间文件夹中的组件。lightning/n/modulesc

提示

有关在启用 LWS 的情况下进行调试的信息,请参阅在启用了 LWS 的组织中调试组件。

启用自定义格式化程序

启用自定义格式化程序时,可以使用更多调试功能。

在 Chrome DevTools 中,选择“设置”() |首选项 |控制台 |启用自定义格式化程序

Lightning Web 组件的自定义格式化程序允许您查看代理对象中包含的实际值。虽然在调试时看不到代理对象,但它们仍然存在并阻止修改。自定义格式化程序可以在不删除代理的情况下查看代理。

提示

如果在组织中启用了 Lightning Web Security,则自定义格式化程序还允许您在 DevTools 控制台中查看其他消息和筛选的调用堆栈。请参阅在启用了 LWS 的组织中调试组件。

来自 LWC 引擎的控制台警告

在调试模式下,Lightning Web 组件引擎会识别仅在运行时才能检测到的不良模式,并将其打印为控制台警告。

最佳做法是使用调试模式在组织中开发 Lightning Web 组件。您可以在开发时使用 LWC 引擎的反馈来改进代码。

仅筛选您自己的组件的一种方法是删除“info”日志级别以隐藏堆栈跟踪。

调试线适配器

使用调试模式对具有未缩小的 JavaScript 和自定义格式的电线适配器进行故障排除。

调试电线适配器的最简单方法是通过 Chrome DevTools。

调试电线适配器:

  1. 启用调试模式。
  2. 在 Chrome DevTools 中,启用自定义格式化程序。

当您通过 接收数据时,您的数据将绑定到函数或属性。@wire

检查有线功能

如果使用有线函数,则可以根据 Chrome DevTools 的 Sources 面板中的解构和属性进行调试。dataerror

或者,您可以使用下一节中介绍的方法调试有线函数。

检查有线属性或方法

如果在组件上使用有线属性或方法,则可通过自定义对象格式化程序获取调试信息。

每个有线属性或方法都返回具有以下形状的信息:

  • data– 电线适配器返回的最后一个值
  • config– 报告给电线适配器的最后一个配置
  • context– 仅适用于上下文线适配器
  • isDataProvisionedForConfig– 一个布尔值,用于返回线路适配器配置的数据是否与配置相对应。如果报告了配置,则返回 .true

提示

lwc-recipes 存储库具有使用有线属性的 apexWireMethodToProperty 组件。

使用或检查呈现的 LWC 自定义元素检查组件实例。例如,单击 Chrome DevTools 的“元素”面板中的元素。this<c-apex-wire-method-to-property>

单击该元素后,打开“控制台”面板并输入 $0 以返回调试信息。

在启用了 LWS 的组织中调试组件

当您在启用了使用 Lightning Web Security 的组织中调试 Lightning Web 组件时,您会注意到与未启用 Lightning Web Security 的组织相比存在一些差异。

首先,确保启用调试模式以获得最佳调试体验。

对于由 LWS 沙盒处理的代码,调试技术通常是相同的,但让我们来看看一些差异。

LWS 下 LWC 调试的源代码位置

从 24 年冬季开始,当您使用 Chrome DevTools 调试 Lightning Web 组件时,您的组件源代码将显示在文件夹内的“源”面板中。此位置在“源”面板中的“查找代码”中进行了介绍。无论启用 Lightning Locker 还是 LWS,位置都是相同的。lightning/n/modules

以前,当您的 Lightning Web 组件在启用了 Lightning Web Security 的组织中运行时,一个特殊的文件夹会将您的组件文件单独组织在命名空间文件夹下。lws

在这里,您可以在当前页面上看到命名空间及其组件。启用了 LWS 的文件与源映射一起显示。ccompositionBasics.js

源代码映射使沙盒代码看起来与组件的原始源代码相似。您可以检查它、使用断点等。您必须启用调试模式才能查看源映射并启用断点。

提示

如果“源”面板中的代码看起来与您的原始源代码不同,请确保已启用在 Chrome DevTools 中启用 JavaScript 源映射设置。默认情况下,它处于启用状态。

如果已在调试器中,还可以在“页面”窗格中找到源文件。右键单击并选择在边栏中显示

此处,调试器停止,但未在侧边栏中选择该文件。当您选择“在边栏中显示”时,将选择正确的文件。compositionContactSearch.js

LWS 下 Aura 组件调试的源码位置

调试 Aura 组件时,源代码将显示在“源”面板中,该子文件夹位于以组织命名的文件夹内。lightning/n/components

文件夹的确切位置可能因浏览器和会话而异,还取决于您使用组件的方式。如果您没有立即看到该文件夹,请展开节点,直到找到它。lightning/n/components

此示例显示了 lwc-recipes 中的 Aura Interop 组件。顶部文件夹名称与包含该组件的 Lightning 页面的名称匹配。突出显示的文件用于调试。Aura_Interoperability

控制台堆栈跟踪

控制台中的堆栈跟踪显示会过滤掉 LWS 调用,以便更清楚地了解组件中的错误。LWS 调用包含在其自己的文件夹 (1) 中。

若要查看筛选的堆栈跟踪,请启用自定义格式化程序,如启用自定义格式化程序中所述。

控制台消息

控制台消息在控制台方法(如 和 )中显示有关 LWS 的信息。例如,当在沙盒的一侧而不是另一侧跟踪对象突变时调用。console.warnconsole.infoconsole.warn

要查看 LWS 控制台消息,请启用自定义格式化程序,如启用自定义格式化程序中所述。

注意

LWS 更改控制台消息的源代码行号和源代码文件。控制台消息似乎来自 Salesforce 文件,而不是来自记录消息的组件的 JavaScript 文件。此行为是由于浏览器实现导致的已知问题,因此我们正在等待浏览器供应商实现修复。aura_proddebug.js

调试移动组件

您可以使用 Chrome DevTools 中的设备模式等工具,在桌面浏览器中测试移动基础知识,例如小屏幕尺寸和响应式设计。要查看特定于移动设备的功能,请在真实移动设备上使用 Salesforce Mobile 应用程序。

借助 Lightning 移动版,桌面版和移动版 Salesforce 提供相同的用户界面:Lightning Experience。这意味着,虽然它不能替代在实际移动设备上进行全面测试,但您可以使用桌面浏览器来运行和调试移动 Lightning 应用程序和组件的许多方面。

借助 Chrome DevTools 设备模式,您可以模拟移动设备的以下方面:

  • 屏幕尺寸
  • 设备方向
  • 位置更改
  • 移动设备 CPU 限制
  • 无线网络限制

要了解有关设备模式的更多信息,请参阅 Google Chrome DevTools 网站上的在 Chrome DevTools 中使用设备模式模拟移动设备。

将 Aura 组件迁移到 Lightning Web 组件

Aura 组件和 Lightning Web 组件可以存在于同一个应用程序中。本部分通过将概念从 Aura 组件映射到 Lightning Web 组件,帮助您迁移组件并应用现有技能。

有关如何将概念从 Aura 组件映射到 Lightning Web 组件的图形说明,请参阅此 Medium 帖子。

适用于 Aura 开发人员的 Lightning Web 组件 Trailhead 模块是帮助您了解 Lightning Web 组件的另一个资源。

迁移策略

Lightning Web 组件的编程模型与 Aura 组件的模型根本不同。迁移组件不是逐行转换,这是重新审视组件设计的好机会。在迁移 Aura 组件之前,请评估组件的属性、接口、结构、模式和数据流。

最容易迁移的组件是仅呈现 UI 的简单组件。通过迁移更大的组件树(组件中的组件)而不是单个组件,您可以获得更高的性能和开发人员的工作效率。但是,迁移一个组件并查看 Aura 编程模型中的概念如何映射到 Lightning Web 组件编程模型中的概念是一种有用的学习体验。

迁移一个组件后,你将能够更好地确定你和你的组织是否有必要:

  • 进行更大规模的迁移工作
  • 仅将 Lightning Web 组件用于新组件
  • 暂时坚持使用 Aura 组件

选择权由您决定,每个人的选择都不同,具体取决于用例和可用资源。无论您做出什么决定,迁移组件都是一项有价值的学习练习。

选择要迁移的组件

要决定是否迁移组件,首先要了解 Aura 组件和 Web 组件如何协同工作,然后评估组件的使用方式和位置。

在选择要迁移的组件之前,请确保您了解 Aura 组件中的分面概念。

让我们回顾一下有关 Lightning Web 组件和 Aura 组件如何协同工作的最重要的事实。

  • Lightning Web 组件和 Aura 组件可以在同一运行时中共存。
  • Aura 组件可以包含 Lightning Web 组件。
  • Lightning Web 组件不能包含 Aura 组件。
  • 如果 Aura 组件具有包含其他 Aura 组件的 face,则您也必须迁移这些其他 Aura 组件。

迁移组件包文件

Aura 编程模型与 Lightning Web 组件编程模型的组件包文件结构不同。

以下是文件在两个编程模型之间的映射方式。

资源Aura 文件闪电网络组件文件另见
标记sample.cmpsample.html组件 HTML 文件
控制器sampleController.jssample.js组件 JavaScript 文件
助手sampleHelper.jssample.jsLightning 组件开发人员指南:帮助程序
渲染sampleRenderer.jssample.jsLightning 组件开发人员指南:渲染器
CSS的sample.csssample.css组件 CSS 文件
文档sample.auradoc目前不可用Lightning 组件开发人员指南:组件文档
设计sample.designsample.js-meta.xml组件配置文件
SVGsample.svg目前不可用Lightning 组件开发人员指南:自定义图标

注意

Aura 组件中的控制器、帮助程序和渲染器文件映射到 Lightning Web 组件中的一个 JavaScript 文件。

迁移标记

Aura 文件包含标记,包括特定于 Aura 的标签。让我们看看此标记如何映射到 Lightning Web 组件中的等效概念。.cmp

迁移属性

将属性从 Aura 组件中的标签迁移到 Lightning Web 组件中的 JavaScript 属性。<aura:attribute>

让我们看一下 Aura 组件中的属性。myAttribute

<aura:component>
  <aura:attribute name="myAttribute" default="Hello" />
</aura:component>

在 Lightning Web 组件中,我们改用名为 JavaScript 的属性。myAttribute

// myComponentName.js
import { LightningElement, api } from "lwc";
export default class MyComponentName extends LightningElement {
  @api myAttribute = "Hello";
}

修饰器定义为公共属性。请参阅公共属性。@apimyAttribute

引用组件的 HTML 文件中的属性。

<!-- myComponentName.html -->
<template> {myAttribute} </template>

Lightning Web 组件中的布尔属性值是在标记中设置的,没有指示和值。该值由属性的存在 () 或不存在 () 设置。在 JavaScript 中,可以使用动态计算值设置布尔属性值。如果布尔属性的值计算为 ,则会将其从 DOM 中删除。请参见布尔属性。 truefalsetruefalsefalse

重要

Lightning Web 组件必须完全支持转换后的 Aura 组件的属性。如果没有,则会出现错误和破损。

迁移迭代

将 Aura 组件中的标签迁移到 Lightning Web 组件中。<aura:iteration>for:each

下面是 Aura 语法。

<aura:iteration items="{!v.items}" itemVar="item"> {!item} </aura:iteration>

下面是 Lightning Web 组件语法。

<template for:each={items} for:item="item">
  <p key={item.id}>{item}</p>
</template>

请注意,必须使用 a 为列表中的每个项目分配唯一值。请参阅渲染列表。key

您无法像在 Aura 组件标记中那样初始化 Lightning Web 组件模板中的列表选项。您必须在 JavaScript 中初始化列表选项。有关示例,请参阅 lightning-dual-listbox 组件。

迁移条件语句

将 Aura 组件中的标签迁移到 、 和 Lightning Web 组件中的标签。<aura:if>lwc:iflwc:elseiflwc:else

下面是 Aura 组件中的语法。

<aura:if isTrue="{!v.something}">
  <div>Conditional Code</div>
  <aura:set attribute="else">
    <div>Conditional Code</div>
  </aura:set>
</aura:if>

下面是 Lightning Web 组件中的语法。

<template>
  <div lwc:if={something}>Conditional Code</div>
  <div lwc:elseif={something}>Conditional Code</div>
</template>
import { LightningElement } from "lwc";
export default class MyComponentName extends LightningElement {
  something = true;
}

迁移表达式

将表达式从 Aura 组件中的标记迁移到 Lightning Web 组件中的 JavaScript。

下面是 Aura 组件中的语法。

<aura:if isTrue="{! (!v.something ? v.optionA : v.optionB) }">
  <div>Conditional Code</div>
</aura:if>

在 Lightning Web 组件中,使用表达式并将其移动到 JavaScript 中。现在代码可以进行单元测试,这是一件非常非常好的事情。下面是 HTML 文件。lwc:if

<template>
  <div lwc:if={condition}>Conditional Code</div>
</template>

提示

Lightning Web 组件的 HTML 文件中的动态内容在 getter 引用周围没有引号,也没有感叹号或值提供程序 () 语法。不要使用 Aura 组件中的表达式语法,即使您的手指可能习惯于键入它!v.

下面是 Aura 组件中的表达式。

<aura:if isTrue="{!v.condition}">

下面是 Lightning Web 组件中的类似 HTML。

<div lwc:if={condition}>Conditional Code</div>

下面是 JavaScript 文件。

import { LightningElement } from "lwc";
export default class MyComponentName {
  get condition() {
    return something ? true : false;
  }
}

迁移全球价值提供商

将 Aura 组件中的全局值提供程序迁移到 Lightning Web 组件中的作用域模块导入。

AuraLightning Web 组件描述
$Browser@salesforce/client/formFactor返回有关运行浏览器的硬件的外形规格的信息。
$ContentAsset@salesforce/contentAssetUrl引用在 Lightning 组件中用作资产文件的图像、样式表和 JavaScript。
$Label@salesforce/label访问存储在代码外部的标签。
$Locale@salesforce/i18n返回有关当前用户的首选区域设置的信息。
$Resource@salesforce/resourceUrl引用您在静态资源中上传的图像、样式表和 JavaScript 代码。

迁移初始值设定项

将 Aura 组件中的事件处理程序替换为 Lightning Web 组件中的标准 JavaScript 方法。initconnectedCallback()

我们在 Aura 组件中使用该事件在组件构造之后但在渲染之前初始化组件。init

<aura:handler name="init" value="{!this}" action="{!c.doInit}" />

组件控制器中的函数执行任何必要的初始化。doInit

({
  doInit: function (cmp) {
    // initialize component
  },
});

在 Lightning Web 组件中,改用组件的 JavaScript 文件。connectedCallback()

// mySampleInit.js
import { LightningElement } from "lwc";
export default class MySampleInit extends LightningElement {
  connectedCallback() {
    // initialize component
  }
}

迁移分面

将 Aura 组件中的分面迁移到 Lightning Web 组件中的插槽。

Aura 组件中的分面是类型为 的属性。例如:Aura.Component[]

<aura:component>
  <aura:attribute name="firstName" type="Aura.Component[]" />
  <aura:attribute name="lastName" type="Aura.Component[]" />

  <p>First Name: {!v.firstName}</p>
  <p>Last Name: {!v.lastName}</p>
</aura:component>

在 Lightning Web 组件中,我们使用插槽而不是分面。此模板定义了两个命名槽。

<!-- namedSlots.html -->
<template>
  <p>First Name: <slot name="firstName">Unknown</slot></p>
  <p>Last Name: <slot name="lastName">Unknown</slot></p>
</template>

此代码使用组件。<c-namedslots>

<!-- slotsWrapper.html -->
<template>
  <c-named-slots>
    <span slot="firstName">Willy</span>
    <span slot="lastName">Wonka</span>
  </c-named-slots>
</template>

此 HTML 是呈现的输出。

<p>First Name: <span>Willy</span></p>
<p>Last Name: <span>Wonka</span></p>

迁移基本组件

基本 Lightning 组件是 Salesforce 在命名空间中提供的构建块。当您在两种编程模型中使用基本 Lightning 组件时,它们具有不同的语法。lightning

迁移基本组件标记

此 Aura 组件使用基本组件。lightning:formattedText

<aura:component>
    <lightning:formattedText linkify="true" value="I like salesforce" />
</aura:component>

要将此标记迁移到 Lightning Web 组件:

  • 替换为 .<aura:component></aura:component><template></template>
  • 将分隔命名空间和组件名称的冒号更改为短划线。
  • 验证 Aura 基础 Lightning 组件是否可用作 Lightning Web 组件。请参阅组件库。
  • 将驼峰大小写组件名称 () 更改为以短划线分隔的名称 ()。formattedTextformatted-text
  • 删除布尔属性上的 or 值。如果存在,则布尔属性表示其值为 。truefalsetrue
  • 将自闭合标记更改为完整结束标记 ()。</lightning-formatted-text>

下面是等效的 Lightning Web 组件。

<template>
  <lightning-formatted-text linkify value="I like salesforce"></lightning-formatted-text>
</template>

迁移基本组件事件处理程序

Aura 基础组件上的大多数事件处理程序都具有等效的 Lightning Web 组件。此 Aura 组件使用带有事件处理程序的基本组件。lightning:buttononclick

<aura:component>
    <lightning:button
      label="Submit"
      title="Submit record data"
      onclick="{! c.handleClick }" />
</aura:component>

若要检索触发事件的按钮上的标签,请使用 .clickevent.getSource()

({
  handleClick: function (cmp, event, helper) {
    alert("You clicked: " + event.getSource().get("v.label"));
  },
});

下面是等效的 Lightning Web 组件。

<template>
  <lightning-button label="Submit" title="Submit record data" onclick={handleClick}>
  </lightning-button>
</template>

若要获取对调度事件的组件的引用,请使用该属性,该属性公开了基组件上的公共属性。例如,使用 、 返回单击组件上的标签event.targetlightning-buttonevent.target.label

import { LightningElement } from "lwc";
export default class MigrateButton extends LightningElement {
  clickedButtonLabel;

  handleClick(event) {
    this.clickedButtonLabel = event.target.label;
  }
}

如果基本 Aura 组件使用 HTML 元素包装,以便您可以侦听组件上的 HTML 事件,请将事件处理程序移动到基本 Lightning Web 组件。例如,支持多个事件处理程序,但不支持 .但是,Aura 使您能够创建包装器来处理事件。lightning:inputonkeydowndivkeydown

<div onkeydown="{!c.handleKeyDown}">
  <lightning:input type="search" value="{!v.value}" onchange="{!c.handleChange}" />
</div>

下面是等效的 Lightning Web 组件。

<lightning-input
  value={val}
  label="Enter some text"
  onchange={handleChange}
  onkeydown={handleKeyDown}
>
</lightning-input>

并非 Aura 基本组件中的所有事件处理程序都具有等效的 Lightning Web 组件。有关每个基本组件的规范,请参阅组件库。

迁移注意事项

一些基本的 Lightning Web 组件提供了比 Aura 对应组件更丰富的功能集。某些基本组件可能需要更多更改才能迁移。基本组件:Aura 与 Lightning Web 组件中记录了组件差异。

组件库包括基本组件的示例、文档和规范。在组件的参考页面中,要比较 Lightning Web 组件及其对应的 Aura 组件,请单击“以 Aura 组件形式查看”或“以 Lightning Web 组件形式查看”。

迁移已注册的事件

在 Lightning Web 组件中,Aura 组件标记中的标记没有等效项来注册组件可以触发事件。<aura:registerEvent>

迁移事件处理程序

在 Lightning Web 组件中,没有用于配置事件处理程序的 Aura 组件标记中的标记的等效项。<aura:handler>

迁移访问控制

将 Aura 组件的访问控制迁移到 Lightning Web 组件配置文件中的相应值。将 Aura 组件中属性的访问控制迁移到 JavaScript 属性装饰器和值的适当组合。<isExposed><isExposed>

要管理对 Aura 捆绑包资源(如组件或属性)的访问,请使用 system 属性。例如,此组件具有全局访问权限,这意味着该组件可以添加到托管包中并在另一个组织中使用。如果 Aura 组件实现了适当的接口,则还可以在其他组织的 Lightning 应用程序生成器或 Experience Builder 中使用。access

<aura:component access="global">
    ...
</aura:component>

Lightning Web 组件中的访问控制机制不同,其中访问由 JavaScript 属性装饰器和组件的配置文件定义。

元件

以下是 Aura 组件的访问值如何映射到 Lightning Web 组件。公共

仅在您的组织内可用。

在组件的配置文件中设置。<isExposed>false</isExposed>全球

在所有组织中都可用。该组件可以添加到托管包中,并在另一个组织中使用。Aura 组件还可以在其他组织的 Lightning 应用程序生成器或 Experience Builder 中使用。

在组件的配置文件中设置。<isExposed>true</isExposed>

属性

以下是 Aura 属性的访问值如何映射到 Lightning Web 组件。私人

仅在组件中可用。

使用 JavaScript 字段。公共

仅在您的组织内可用。

在 Lightning Web 组件中执行这两个步骤。

  1. 将 JavaScript 字段与装饰器一起使用。@api
  2. 在组件的配置文件中设置。<isExposed>false</isExposed>

全球

在所有组织中都可用。

在 Lightning Web 组件中执行这两个步骤。

  1. 将 JavaScript 属性与装饰器一起使用。@api
  2. 在组件的配置文件中设置。<isExposed>true</isExposed>

迁移事件

将 Aura 组件中的组件事件迁移到 Lightning Web 组件中的标准 DOM 事件。

以下是在 Lightning Web 组件中处理事件的概述。创建活动

而不是 Aura 组件中的专有对象,而是使用或标准 DOM 对象。在 Lightning Web 组件中,Aura 组件标记中的标记没有等效项来注册组件可以触发事件。EventEventCustomEvent<aura:registerEvent>触发事件

在 Lightning Web 组件中使用 ,而不是在 Aura 组件中使用 ,这是一种标准的 DOM 方法。event.fire()this.dispatchEvent(myEvent)处理事件

Aura 组件使用标记中的标记来定义处理程序。或者,当组件在其标记中引用另一个组件时,它可以声明处理程序操作。此 Aura 组件在其标记中使用,并为触发的 声明一个处理程序。<aura:handler>c:childhandleChildEventsampleComponentEventc:child

<c:child sampleComponentEvent="{!c.handleChildEvent}" />

Lightning Web 组件可以类似地声明声明性处理程序。声明性处理程序中的事件名称以 为前缀。on<!– prettier-ignore –>

<c-child onsampleComponentEvent={handleChildEvent}></c-child>

事件处理程序函数 在组件的 JavaScript 文件中定义。handleChildEvent

在 Lightning Web 组件中,您还可以使用组件的 JavaScript 文件中的标准方法以编程方式设置处理程序。addEventListener()检索事件负载

除非另有说明,否则使用该属性检索事件有效负载。event.detail

迁移应用程序事件

使用 Lightning 消息服务 (lightning/messageService) 与单个页面或多个页面中的组件进行通信。您还可以使用 pub-sub 模式在单个页面中的组件之间进行通信。

迁移标准Aura事件

此表将标准 Aura 事件(例如用于导航到组件或显示记录创建面板)映射到 Lightning Web 组件中的使用情况。未列出的事件目前在 Lightning Web 组件中没有等效事件。

Aura 组件Lightning Web 组件描述
aura:locationChange当窗口的哈希值更改时,将触发浏览器事件。若要处理此事件,请使用 onhashchange 事件处理程序。hashchange在浏览器位置栏中 URL 的哈希部分被修改时触发。
aura:valueChange将属性与自定义 getter 和 setter 方法结合使用。在属性值更改时触发。
aura:valueDestroy使用生命周期钩子。请参阅组件生命周期。disconnectedCallback()当组件被销毁时触发。
aura:valueInit若要替换事件处理程序,请使用生命周期挂钩。请参阅迁移初始值设定项。initconnectedCallback()在组件初始化时触发。
aura:valueRender使用 或 lifecycle 挂钩。请参阅组件生命周期。renderedCallback()render()在渲染组件时触发。
force:createRecord使用导航服务。显示记录创建面板。
force:editRecord使用导航服务。显示记录编辑面板。
force:navigateHome(已弃用)使用导航服务。导航到记录主页。
force:navigateToComponent(已弃用)使用导航服务。导航到组件。
force:navigateToList使用导航服务。导航到列表视图。
force:navigateToObjectHome使用导航服务。导航到对象主页。
force:navigateToRelatedList使用导航服务。导航到相关列表。
force:navigateToSObject使用导航服务。导航到记录。
force:navigateToURL使用导航服务。导航到 URL。
force:refreshView要刷新通过线路服务预配的 Apex 数据,请调用 refreshApex()。如果您的代码强制调用 Apex 方法,请通过再次调用该方法来刷新数据,然后调用 notifyRecordUpdateAvailable(recordIds) 以更新 Lightning 数据服务 (LDS) 缓存。仅当您希望在 LDS 缓存中更新任何相关数据时,才需要调用。向 LDS 发出某些记录已过时的信号,并刷新 LDS 缓存中的那些记录。notifyRecordUpdateAvailable()notifyRecordUpdateAvailable()在不重新加载页面的情况下重新加载视图。
force:showToast导入模块。请参阅 Toast 通知lightning/platformShowToastEvent显示 Toast 消息,以提醒用户成功、错误或警告。
lightning:openFiles使用导航服务。请参阅打开文件。打开一条或多条文件记录。
lightning:tabClosed计划在将来发布。在成功关闭控制台工作区或子选项卡时触发。
lightning:tabCreated计划在将来发布。在成功创建控制台工作区或子选项卡时触发。
lightning:tabFocused计划在将来发布。当控制台工作区或子选项卡处于焦点状态时触发。
lightning:tabRefreshed计划在将来发布。在成功刷新控制台工作区或子选项卡时触发。
lightning:tabReplaced计划在将来发布。在成功替换控制台主选项卡或子选项卡时触发。
lightning:tabUpdated计划在将来发布。在控制台工作区或子选项卡更新(包括标签、图标或其他内容更改)时触发。
ltng:afterScriptsLoaded从模块导入静态资源和导入方法。请参阅使用第三方 JavaScript 库。lightning/platformResourceLoader在加载了ltng:requireltng:require.scripts

注意

我们的前瞻性声明适用于计划在未来版本中的功能支持。由于路线图项目可能随时更改,因此请根据当前可用的技术做出购买决策。

迁移接口

通过实施 Aura 接口,您可以接收上下文数据或在不同的上下文中显示自定义组件,例如在 Lightning 应用程序生成器或体验生成器中。

要在 Lightning Web 组件中接收上下文数据,请导入相应的模块。若要在不同的上下文中显示组件,请使用配置文件中的元数据。targets*.js-meta.xml

未列出的 Aura 接口目前在 Lightning Web 组件中没有等效接口。

客户端:availableForMailAppPage

在:*.js-meta.xml

<targets>
  <target>lightning__Inbox</target>
</targets>

指示该组件可在 Lightning 应用程序构建器中用于添加到 Outlook 和 Gmail 集成的电子邮件应用程序窗格中。 请参阅为 Outlook 和 Gmail 集成创建组件。

客户端:hasEventContext

import { LightningElement, api } from 'lwc';
  @api dates;
  @api location;

在:*.js-meta.xml

<targets>
  <target>lightning__Inbox</target>
</targets>

指示组件在与 Outlook 和 Gmail 集成一起使用时获取有关事件的上下文信息。请参阅为 Outlook 和 Gmail 集成创建组件。

客户端:hasItemContext

import { LightningElement, api } from 'lwc';
  @api mode;
  @api people;
  @api source;
  @api subject;
  @api messageBody;

*.js-meta.xml:

<targets>
  <target>lightning__Inbox</target>
</targets>

指示组件在与 Outlook 和 Gmail 集成一起使用时获取有关电子邮件或日历事件的上下文信息。请参阅为 Outlook 和 Gmail 集成创建组件。

flexipage:availableForAllPageTypes

*.js-meta.xml:

<targets>
  <target>lightning__AppPage</target>
  <target>lightning__RecordPage</target>
  <target>lightning__HomePage</target>
  <target>lightning__UtilityBar</target>
</targets>

指示该组件可用于记录页、实用工具栏和任何其他类型的页。将每个页面类型显式指定为目标。请参阅为 Lightning 应用程序生成器配置组件和为实用程序栏配置组件。

flexipage:availableForRecord首页

<targets>
  <target>lightning__RecordPage</target>
</targets>

指示该组件仅适用于记录页。

force:hasRecordId

import { LightningElement, api } from 'lwc';
  @api recordId;

*.js-meta.xml:

<targets>
  <target>lightning__RecordPage</target>
</targets>

指示组件采用记录 ID 作为属性。请参阅使组件了解其记录上下文。

force:hasSObjectName

import { LightningElement, api } from 'lwc';
  @api objectApiName;

*.js-meta.xml:

<targets>
  <target>lightning__RecordPage</target>
</targets>

指示组件采用当前记录的对象类型的 API 名称。请参阅使组件了解其对象上下文。

力:闪电快速动作

*.js-meta.xml:

<targets>
  <target>lightning__RecordAction</target>
</targets>
<targetConfigs>
  <targetConfig targets="lightning__RecordAction">
    <actionType>ScreenAction</actionType>
  </targetConfig>
</targetConfigs>

指示组件是快速操作。请参阅配置组件以执行快速操作。

注意

LWC 快速操作目前仅在记录页面上受支持。

force:lightningQuickActionWithoutHeader

*.js-meta.xml:

<targets>
  <target>lightning__RecordAction</target>
</targets>
<targetConfigs>
  <targetConfig targets="lightning__RecordAction">
    <actionType>ScreenAction</actionType>
  </targetConfig>
</targetConfigs>

指示组件是没有标头的快速操作。请参阅配置组件以执行快速操作。

注意

LWC 快速操作目前仅在记录页面上受支持。

forceCommunity:availableForAllPageTypes

*.js-meta.xml:

<targets>
  <target>lightningCommunity__Page</target>
</targets>

指示该组件可在Experience Builder中使用。请参阅为 Experience Builder 配置组件。

lightning:hasPageReference

import { CurrentPageReference } from 'lightning/navigation';
  @wire(CurrentPageReference) pageRef;

指示组件接受 PageReference。请参阅导航到页面、记录和列表。

迁移 CSS

Lightning Web 组件使用标准的 CSS 语法。删除 Aura 组件使用的专有类。THIS

下面是 Aura 组件的 CSS 文件。

.THIS .red {
  background-color: red;
}

.THIS .blue {
  background-color: blue;
}

.THIS .green {
  background-color: green;
}

删除 THIS 关键字

迁移的 Lightning Web 组件的 CSS 文件是相同的,只是删除了 .THIS

.red {
  background-color: red;
}

.blue {
  background-color: blue;
}

.green {
  background-color: green;
}

迁移基本 Lightning 组件的 CSS

目前,并非所有基本组件都支持迁移 CSS 文件。假设您正在迁移以下 Aura 标记。lightning:button

<lightning:button label="Reset" class="buttonColor buttonText"/>

使用以下 CSS 选择器。lightning:button

.THIS .buttonColor {
  background-color: red;
}

.THIS .buttonText {
  color: lightgray;
}

当您使用 Lightning Web 组件时,自定义类将应用于组件的外部元素,这意味着以下标记不会显示预期的样式。lightning-buttonlightning-buttonlightning-button

<!-- Custom styling does not work here -->
<lightning-button label="Reset" class="buttonColor buttonText"></lightning-button>

注意

您的自定义 CSS 会自动将范围限定为您自己的组件,以防止基本组件内部的样式化。我们建议您尽可能使用 Lightning Design System 类或基本 Lightning 组件上的变体。

在这种情况下,我们建议您使用 上的 variant 属性。例如,使用变体将背景颜色设置为红色。lightning-buttondestructive

<lightning-button label="Reset" variant="destructive"></lightning-button>

让我们看一下另一个示例,其中迁移 CSS 可以适用于基本组件。例如,您有以下标记。lightning:formattedAddress

<div class="mailingAddress">
  <lightning:formattedAddress
    street="1 Market St."
    city="San Francisco"
    country="US"
    province="CA"
    postalCode="94105"
  />
</div>

该组件使用以下 CSS 选择器。

.THIS .mailingAddress a {
  color: red;
}

使用该属性应用自定义样式。class

<!-- Custom styling works here -->
<lightning-formatted-address
  class="mailingAddress"
  street="121 Spear St."
  city="San Francisco"
  country="US"
  province="CA"
  postal-code="94105"
></lightning-formatted-address>
.mailingAddress {
  color: red;
}

迁移 JavaScript

将 JavaScript 代码从客户端控制器、帮助程序和渲染器移动到 Lightning Web 组件中的单个 JavaScript 文件。

Aura 组件中的客户端控制器是采用对象文字表示法的 JavaScript 对象,其中包含名称/值对的映射。Lightning Web 组件中的 JavaScript 文件是 ES6 模块,因此您使用的是标准 JavaScript,而不是 Aura 组件中使用的专有格式。

这不是逐行转换,而是重新审视组件设计的好机会。

要在 Lightning Web 组件和 Aura 组件之间共享 JavaScript 代码,请将代码放在 ES6 模块中。有关更多信息,请参阅在 LWC 和 Aura 之间共享 JavaScript 代码。

迁移 Apex

Aura 组件和 Lightning Web 组件都使用 Apex 控制器来读取或保存 Salesforce 数据。这两种编程模型没有语法差异。

Lightning Web 组件还可以使用 JavaScript 装饰器来包装对 Apex 方法或用户界面 API 的调用。@wire

数据绑定行为与 Aura 的差异

在标记中添加组件时,可以根据所有者组件的属性值初始化组件中的公共属性值。在 Lightning Web 组件中,属性值的数据绑定是单向的。Lightning Web 组件和 Aura 开发模型的数据绑定行为是不同的。

Aura

Aura 有两种形式的数据绑定表达式语法。

下面总结了表达式语法形式之间的差异。{#expression}(未绑定表达式)

数据更新的行为与您在 JavaScript 中的预期一样。基元(如 )按值传递,父项和子项中表达式的数据更新是分离的。String

对象(如 或 )通过引用传递,因此对子项中数据的更改将传播到父项。但是,父级中的更改处理程序不会收到通知。相同的行为也适用于传播到子项的父项中的更改。ArrayMap{!expression}(绑定表达式)

任一组件中的数据更新都通过两个组件中的双向数据绑定进行反映。同样,更改处理程序在父组件和子组件中都会触发。

Lightning Web 组件

属性值的组件之间的数据绑定是单向的。

若要从父组件向下通信到子组件,请在子组件上设置属性或调用方法。

若要从子组件向上通信到父组件,请发送事件。

有关更多信息,请参见设置子组件的属性。

基本组件:Aura 与 Lightning Web 组件

许多基本的 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

表 1.Aura 组件到 Lightning Web 组件的映射

NamespaceAura 组件Lightning Web 组件差异
lightningaccordionaccordionlightning:accordion支持在简单标记中初始化多个打开的部分。要使用多个打开的部分进行初始化,请使用 JavaScript 传递部分名称数组。lightning-accordion
lightningaccordionSectionaccordion-sectionlightning:accordionSection通过传入组件的 actions 属性支持自定义菜单。当您将鼠标悬停在折叠式部分上时,Aura 组件的属性会提供工具提示文本。 支持通过插槽执行自定义菜单操作。Lightning Web 组件中的属性目前保留供内部使用。actionslightning:buttonMenutitlelightning-accordion-sectionactionslightning-button-menutitle
lightningavataravatar
lightningbadgebadge
lightningbreadcrumbbreadcrumb
lightningbreadcrumbsbreadcrumbs
lightningbuttonbutton
lightningbuttonGroupbutton-group
lightningbuttonIconbutton-iconlightning-button-icon不支持 .iconClass
lightningbuttonIconStatefulbutton-icon-stateful
lightningbuttonMenubutton-menulightning:buttonMenu不支持 AND 事件处理程序。onclickonclose
lightningbuttonStatefulbutton-stateful在 中,使用属性在选择按钮时显示。在 中,使用属性。lightning:buttonStatefulstatelightning-button-statefulselected
lightningcardcard在 中,可以将 和 属性设置为字符串或对象,这样就可以传递组件。您可以使用该属性指定要在卡片标题中显示的 或。在 中,可以将 和 属性设置为仅文本。若要包含标记或其他组件,请使用命名槽。您只能在命名槽中指定操作。lightning:cardtitlefooteractionslightning:buttonlightning:buttonIconlightning-cardtitlefooteraction
lightningcarouselcarousel
lightningcheckboxGroupcheckbox-group
lightningclickToDialclick-to-dial
lightningcomboboxcombobox
lightningcontainerLightning Web 组件尚不可用。
lightningdatatabledatatablelightning:datatable不支持表格单元格中的自定义数据类型。 仅支持自定义 CSS 类,用于设置标准数据类型列的样式。 支持表格单元格中的自定义数据类型。 支持自定义 CSS 类,仅用于设置自定义数据类型的列样式。lightning:datatablelightning-datatablelightning-datatable
lightningdualListboxdual-listbox
lightningdynamicIcondynamic-icon
lightningfileCardLightning Web 组件尚不可用。
lightningfileUploadfile-upload
lightningflexipageRegionInfo在 Aura 中,用于使包含组件知道它可以占用的宽度。在 Lightning Web 组件中,将公共属性用于此目的。请参阅使组件具有宽度感知能力。flexipageRegionInfoflexipageRegionWidth
lightningflowflow请参阅在自定义 LWC 中创建和启动流。
lightningformattedAddressformatted-address
lightningformattedDateTimeformatted-date-time在 中,使用 true 或 false 字符串或变量设置属性。在 中,只能使用变量设置属性。字符串始终被解释为 true。lightning:formattedDateTimehour12lightning-formatted-numberhour12
lightningformattedEmailformatted-email
lightningformattedLocationformatted-location
lightningformattedNameformatted-name
lightningformattedNumberformatted-number在 中,使用属性指定要显示的数字类型。在 中,将属性用于此目的。lightning:formattedNumberstylelightning-formatted-numberformat-style
lightningformattedPhoneformatted-phone
lightningformattedRichTextformatted-rich-text
lightningformattedTextformatted-text
lightningformattedTimeformatted-time
lightningformattedUrlformatted-url
lightninghelptexthelptext
lightningiconicon
lightninginputinput
lightninginputAddressinput-address
lightninginputFieldinput-fieldlightning:inputField不提供指示字段已修改但未保存的方法。 支持一个属性,以指示该字段已被用户修改,但未保存或提交。有关详细信息,请参阅差异。 支持该属性,但同时支持 和 。lightning-input-fielddirtyrecordEditFormlightning:inputFieldreadonlylightning-input-fieldreadonlyread-only
lightninginputLocationinput-location
lightninginputNameinput-name
lightninginputRichTextinput-rich-textlightning:inputRichText要求您使用子组件添加“插入图像”按钮。它不支持插入链接按钮或自定义按钮。 提供用于插入图像和链接的按钮。 支持使用组件和 (Beta) 添加自定义按钮。lightning:insertImageButtonlightning-input-rich-textlightning-input-rich-textlightning-rich-text-toolbar-button-grouplightning-rich-text-toolbar-button
lightninginsertImageButton支持插入图像按钮,因此您不需要 .lightning-input-rich-textlightning:insertImageButton
lightninglayoutlayoutlightning:layout允许组件之间的 HTML 标记、文本、表达式和其他组件。 不允许在组件之间使用表达式或其他组件。但是,您可以在组件之间放置 HTML 标记和文本。lightning:layoutItemlightning-layoutlightning-layout-itemlightning-layout-item
lightninglayoutItemlayout-item请参阅的差异。lightning-layout
lightninglistViewLightning Web 组件尚不可用。
lightningmapmap
lightningmenuItemmenu-item
lightningnavigationnavigation模块在 Aura 组件中,使用该组件访问导航服务。在 Lightning Web 组件中,在组件的 JavaScript 中导入模块。请参阅导航到页面、记录和列表。lightning:navigationlightning/navigation
lightningnotificationsLibraryplatformShowToastEvent模块在 Aura 组件中,添加组件以创建通知和 Toast。库提供 和 事件。在 Lightning Web 组件中,将模块导入组件的 JavaScript 中。该模块提供了一个名为 的事件。LWC 尚不支持通知。 支持与 Aura 相同的参数、模式和变体。请参阅 Toast 通知。notificationsLibraryshowToastshowNoticelightning/platformShowToastEventShowToastEventShowToastEventshowToast
lightningoutputFieldoutput-field查看差异。recordViewForm
lightningoverlayLibrary在 Aura 组件中,添加组件以创建模式对话框和弹出框。该库提供 、 和方法。overlayLibraryshowCustomModal()showCustomPopover()notifyClose()
lightningpathLightning Web 组件尚不可用。
lightningpicklistPathLightning Web 组件尚不可用。
lightningpillpilllightning:pill要求属性包含头像或图标。该属性在 上不可用。 可以接受头像和图标作为嵌套组件。mediavariantlightning:pilllightning-pill
lightningpillContainerpill-container
lightningprogressBarprogress-bar
lightningprogressIndicatorprogress-indicator
lightningprogressRingprogress-ring
lightningquipCardLightning Web 组件尚不可用。
lightningradioGroupradio-group
lightningrecordEditFormrecord-edit-formlightning:recordEditForm不需要直接将组件嵌套在其中。您可以将组件嵌套在 HTML 标记或其他组件中,例如定制布局。 旨在用作 的子项。您可以嵌套在 HTML 标记或其他基本组件中,例如 within 中。但是,不能嵌套在自定义组件中。lightning:inputFieldlightning:inputFieldlightning:layoutlightning-input-fieldlightning-record-edit-formlightning-input-fieldlightning-layoutlightning-record-edit-formlightning-input-field
lightningrecordFormrecord-form
lightningrecordViewFormrecord-view-formlightning:recordViewForm不需要您直接将组件嵌套在其中,尽管这是预期的用法。 必须是 的子项。不要嵌套在另一个元素中,例如 .您可以将其放置在容器中,例如 within 中。lightning:outputFieldlightning-output-fieldlightning-record-view-formlightning-output-fieldlightning-layoutlightning-record-view-form
lightningrelativeDateTimerelative-date-time
lightningselectLightning Web 组件尚不可用。在移动环境中,使用本机元素。在桌面环境中,请考虑使用 Lightning Web 组件。要支持多选,请使用 .<select>lightning-comboboxlightning-dual-listbox
lightningsliderslider
lightningspinnerspinner
lightningtabtab在 中,使用该属性分配一个字符串来标识选项卡。在 中,使用属性分配选项卡标识符。使用这些字符串来确定单击了哪个选项卡。lightning:tabidlightning-tabvaluetabset
lightningtabsettabsetlightning:tabset使用该属性指定打开的选项卡。 使用 .selectedTabIdlightning-tabsetactive-tab-value attribute
lightningtextareatextarea
lightningtiletile在 中,可用于添加包含头像组件或图标组件的属性。在 中,指定具有命名槽的头像和图标组件。lightning:tile<aura:set\>medialightning-tilemedia
lightningtreetree
lightningtreeGridtree-grid
lightningunsavedChangesLightning Web 组件尚不可用。
lightningverticalNavigationvertical-navigation
lightningverticalNavigationItemvertical-navigation-item
lightningverticalNavigationItemBadgevertical-navigation-item-badge
lightningverticalNavigationItemIconvertical-navigation-item-icon
lightningverticalNavigationItemOverflowvertical-navigation-item-overflow
lightningverticalNavigationSectionvertical-navigation-section
auraexpression自定义 JavaScript请参阅迁移表达式。
aurahtml不适用
auraiflwc:if / lwc:elseif / lwc:else请参阅迁移条件。
auraiterationfor:each请参阅迁移迭代。
aurarenderIflwc:if / lwc:elseif / lwc:else请参阅迁移条件。
auratemplate不适用
auratext不适用
auratoken不适用
auraunescapedHTML不适用
forcecanvasApp不适用
forceinputFieldinput-fieldforce:inputField已被 in Aura 取代。要根据字段类型创建可编辑字段,请使用 Lightning Web 组件或其对应的 Lightning Web 组件。lightning:inputFieldlightning:inputFieldlightning:recordEditForm
forceoutputFieldoutput-fieldforce:outputField已被 in Aura 取代。要根据字段类型创建只读字段,请使用 或其对应的 Lightning Web 组件。lightning:outputFieldlightning:outputFieldlightning:recordViewForm
forcerecordData@wire请参阅了解 Wire Service。
forcerecordEditrecord-edit-formforce:recordEdit已替换为 。lightning:recordEditForm
forcerecordViewrecord-view-formforce:recordView已替换为 。lightning:recordViewForm
ltngrequireplatformResourceLoader模块在 Aura 组件中,将标记添加到组件标记以引用外部静态资源。在 Lightning Web 组件中,将模块导入组件的 JavaScript 中。请参阅使用第三方 JavaScript 库。<ltng:require>lightning/platformResourceLoader

记录主页的 LWC 迁移

作为 Salesforce LWC 支持计划的一部分,标准对象的大多数记录主页都已转换为 LWC,包括详细信息、突出显示和相关列表。

将记录主页转换为使用 LWC 可加快页面加载和呈现速度,这在用于创建、编辑或查看记录的大型页面布局中尤其明显。

记录主页具有此 URL 模式。

https://my-domain-name.my.salesforce.com/lightning/r/ObjectApiName/RecordId/ViewOrEdit

例如,您可以像这样查看帐户的记录主页。

https://my-dev-org.my.salesforce.com/lightning/r/Account/xxxxxxxxxxxxxxxQAD/view

Lightning Web 组件和 Aura 组件协同工作

互操作性层使 Lightning Web 组件和 Aura 组件能够在应用程序中协同工作。

您可以编写新的 Lightning Web 组件,并将其添加到包含 Aura 组件的应用程序中。或者,您可以通过将应用程序中的单个 Aura 组件替换为 Lightning Web 组件来按计划迭代迁移。

Lightning Web 组件和 Aura 组件可以协同工作,但您必须了解一些限制。

重要

Aura 组件可以包含 Lightning Web 组件。但是,反之则不然。Lightning Web 组件不能包含 Aura 组件。

从 Lightning Web 组件编写 Aura 组件

您可以从 Lightning Web 组件组成 Aura 组件,但不能以相反的方式组合。为了在层次结构中向下通信,父级设置子级的属性。要决定何时以及如何将 Lightning Web 组件嵌套在 Aura 组件中,了解分面和插槽非常重要。

在 Aura 组件中,要引用 Aura 组件或 Lightning Web 组件,请使用驼峰大小写,并用冒号分隔命名空间和组件名称。

此 Aura 组件由 ,前者是基本的 Lightning 组件,后者是 Lightning Web 组件。lightning:cardc:lwcHelloWorld

<!-- auraComponent.cmp file -->
<aura:component implements="flexipage:availableForAllPageTypes">
  <lightning:card title="Aura Hello World" iconName="custom:custom30" />
  <c:lwcHelloWorld name="Earthling" />
</aura:component>

该代码显示经典问候语。(它还引用了组件。大多数基本 Lightning 组件都以 Aura 和 LWC 的形式提供。lwcHelloWorldlightning-card

<!-- lwcHelloWorld.html -->
<template>
  <lightning-card title="LWC Hello World" icon-name="custom:custom14">
    <div class="slds-card__body slds-card__body_inner">Hello, {name}!</div>
  </lightning-card>
</template>

该组件具有一个公共属性,Aura 组件使用该属性设置该属性。namename

// lwcHelloWorld.js
import { LightningElement, api } from "lwc";

export default class HelloWorld extends LightningElement {
  @api name;
}

提示

在 trailheadapps/pure-aloe 示例应用程序中,请参阅 Aura irrigationWrapperManager 组件,该组件设置子 irrigationManager Lightning Web 组件的属性。

刻面和插槽

在 Aura 组件和 Lightning Web 组件中,您可以将组件添加到另一个组件的主体中。在 Aura 中,将组件添加到分面中。在 Lightning Web 组件中,您可以将组件添加到插槽中。

在 Aura 中,属性是一个 facet。分面是任何类型的属性,这只是一种奇特的说法,你可以为属性设置一个组件数组。bodyAura.Component[]

用更不花哨的术语来说,把一个切面想象成一个三明治。您可以将任意数量的成分(组件)塞入三明治(切面)中。

<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>

<!-- wrapper.html -->
<template>
  <slot></slot>
</template>

Lightning Web 组件将组件传递到插槽中。c-applightning-card

<!-- app.html -->
<template>
  <c-wrapper>
    <lightning-card>
      <lightning-icon icon-name="utility:connected_apps"></lightning-icon>
      Card Title
      <p class="slds-p-horizontal_small">Card Body</p>
    </lightning-card>
  </c-wrapper>
</template>

重要

如果 Lightning Web 组件包含插槽,您可以将其嵌套在 Aura 组件中,但不能使用该插槽。

从父 Aura 组件调用子 Lightning Web 组件方法

要从 Aura 组件调用 Lightning Web 组件中定义的方法,请为 Lightning Web 组件提供 并使用 ,就像引用 Aura 组件一样。例如。aura:idcmp.find()cmp.find('childLwc').childLwcMethod()

在 Aura 组件渲染之前,不会创建 Lightning Web 组件。在此之前(例如,在 Aura 组件初始化期间),您无法在 Lightning Web 组件上调用方法。

将事件发送到封闭的 Aura 组件

若要从子级与父级进行通信,请调度事件。Lightning Web 组件触发 DOM 事件。封闭的 Aura 组件可以侦听这些事件,就像封闭的 Lightning Web 组件一样。封闭的 Aura 组件可以捕获事件并处理它。(可选)Aura 组件可以触发 Aura 事件,以便与其他 Aura 组件或应用容器进行通信。

提示

lwc-recipes 存储库中的 auraEmbeddedLWC 组件展示了如何在父 Aura 组件中嵌入 Lightning Web 组件并与事件进行通信。

下面的示例演示了此技术。此 Lightning Web 组件在其 JavaScript 文件中触发自定义事件。filterchange

// categoryFilter.js
import { LightningElement } from "lwc";

export default class CategoryFilter extends LightningElement {
  handleCheckboxChange() {
    // Get the labels of selected checkboxes
    const filters = Array.from(this.template.querySelectorAll("lightning-input"))
      .filter((element) => element.checked)
      .map((element) => element.label);
    const filterChangeEvent = new CustomEvent("filterchange", {
      detail: { filters },
    });
    // Fire the custom event
    this.dispatchEvent(filterChangeEvent);
  }
}
<!-- categoryFilter.html -->
<template>
  <lightning-input
    label="Category 1"
    type="checkbox"
    onchange={handleCheckboxChange}
  ></lightning-input>
  <lightning-input
    label="Category 2"
    type="checkbox"
    onchange={handleCheckboxChange}
  ></lightning-input>
</template>

封闭的 Aura 组件包装器为自定义事件添加处理程序。请注意,事件处理程序 与前缀为“on”的事件名称匹配。也就是说,用于处理名为 的事件。onfilterchangeonfilterchangefilterchange

<!-- auraDomEventListener.cmp -->
<aura:component implements="flexipage:availableForAllPageTypes">
    <aura:attribute name="message" type="String" default="No selection"/>

    <lightning:card title="AuraDomEventListener" iconName="custom:custom30">
        <aura:set attribute="actions">
            <span class="aura">Aura Component</span>
        </aura:set>
        <div class="slds-m-around_medium">
            <lightning:layout>
                <lightning:layoutItem size="4">
                    <!-- This is an LWC component -->
                    <c:categoryFilter onfilterchange="{!c.handleFilterChange}"/>
                </lightning:layoutItem>
                <lightning:layoutItem size="8" class="slds-p-left_medium">
                    {!v.message}
                </lightning:layoutItem>
            </lightning:layout>
        </div>
    </lightning:card>
</aura:component>

注意

您只能在 DOM 事件冒泡到的第一个 Aura 组件中指定一个处理程序。onfilterchange

Aura 组件的控制器接收事件。您可以随心所欲地处理该事件。此组件对在 Lightning Web 组件事件的属性中传递的数组进行操作。您可以选择触发新的 Aura 事件以与其他 Aura 组件进行通信。filtersdetails

// auraDomEventListenerController.js
({
  handleFilterChange: function (component, event) {
    var filters = event.getParam("filters");
    component.set(
      "v.message",
      filters.length > 0 ? "Your selection: " + filters.join() : "No selection",
    );
  },
});

在 LWC 和 Aura 之间共享 JavaScript 代码

要在 Lightning Web 组件和 Aura 组件之间共享 JavaScript 代码,请将代码放在服务组件的 ES6 模块中。

要共享 ES6 模块:

  1. 使用 Lightning Web 组件编程模型创建服务组件(库)。
  2. 要在 Lightning Web 组件中使用代码,请在组件的 JavaScript 文件中导入并引用它。
  3. 若要在 Aura 组件中使用代码,请使用导入 Aura 组件并调用其方法时所用的相同语法。有关示例代码,请参阅 Aura lightning:navigationItemAPI 组件文档。请注意,这是一个 Aura 组件,而不是 ES6 模块,但要导入 ES6 模块,请使用相同的 Aura 语法。lightning:navigationItemAPI

提示

lwc-recipes 存储库有一个模块,用于实现 Lightning Web 组件和 Aura 组件之间的通信。该模块已停用,但可以在不支持 Lightning 消息服务的 Experience Cloud 等容器中使用。lmsPublisherWebComponentpubsub

将 Salesforce 外部的组件与 Lightning Out(测试版)配合使用

使用 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 事件进行处理。

除了一些简单的标记外,Salesforce 中还有少量的设置和准备工作,以实现 Salesforce 和源服务器之间的安全连接。而且,由于源服务器托管应用程序,因此您需要使用自己的代码管理身份验证。

此设置过程类似于您对使用 Lightning Platform REST API 连接到 Salesforce 的应用程序执行的操作,您应该期望它需要同等的工作量。

闪电输出要求

使用 Lightning Out 部署 Lightning Web 组件需要满足一些要求,以确保连接性和安全性。

远程 Web 容器

验证远程 Web 容器或源服务器是否支持这些要求。

  • 能够修改提供给客户端浏览器的标记,包括 HTML 和 JavaScript。您必须能够添加 Lightning Out 标记。
  • 能够获取有效的 Salesforce 会话 ID。
  • 能够访问您的 Salesforce 实例。例如,如果源服务器位于防火墙后面,则它需要访问Internet的权限,至少可以访问Salesforce。

闪电储物柜

使用 Lightning Locker,这是 Lightning 组件的安全体系结构。启用 Lightning Web Security 时,不支持 Lightning Out。我们建议将 Lightning Web Security 作为大多数组织的首选安全架构,但如果您使用 Lightning Out,则必须改用 Lightning Locker。

Salesforce组织

配置您的 Salesforce 组织。

  • 创建连接的应用程序,以便源服务器可以进行身份验证和连接。
  • 将源站加入跨域资源共享(CORS)白名单。

Lightning 依赖应用程序

创建一个特殊的独立 Aura 应用程序,其中包含源服务器上托管的所有 Lightning Web 组件的依赖关系信息。此应用程序仅供 Lightning Out 使用。

浏览器第三方 Cookie

要使用 Lightning Out,您必须设置自定义域,或者您的 Safari 用户必须更改其跨站点跟踪浏览器设置。此要求适用于桌面和移动设备上的 Safari 用户。有关更多详细信息,请参阅为闪电输出启用浏览器第三方 Cookie。

启用浏览器第三方 Cookie 以实现闪电输出

Lightning 组件在用户的浏览器中设置 Cookie。由于 Lightning Out 在 Salesforce 外部运行 Lightning 组件,因此这些 Cookie 是“第三方”Cookie。有几种替代方法可以使这些第三方 Cookie 在 Lightning Out 中发挥作用。

启用基于令牌的身份验证

Salesforce 使用 Cookie 进行身份验证。对于 Lightning Out 应用程序,我们建议您启用在 Lightning 应用程序处于第三方上下文中时将身份验证 Cookie 替换为会话令牌的设置。

在“设置”的“快速查找”框中,输入“会话”,然后选择“会话设置”。在“会话设置”页面上,选择“在第三方站点中嵌入 Lightning 应用程序时,请使用会话令牌而不是会话 Cookie”。

如果未启用此设置,则用户必须在其浏览器设置中允许第三方 Cookie。

在 Safari 中启用跨站点跟踪

Salesforce 使用身份验证 Cookie 以外的 Cookie。要使这些来自 Salesforce 的第三方 Cookie 正常工作,您的用户必须在其浏览器设置中允许第三方 Cookie。

默认情况下,“阻止跨站点跟踪”设置在 iOS 和 iPadOS 13.4 以及 Safari 浏览器 13.1 及更高版本中处于启用状态。若要允许第三方 Cookie 并使用 Lightning Out,必须禁用此设置。

要查看“阻止跨网站跟踪”设置,请执行以下操作:

  • 在 Mac 桌面上的 Safari 浏览器 App 中,前往 Safari |首选项,然后单击隐私。
  • 在 iOS 和 iPadOS 中,前往“设置”|”苹果浏览器

设置自定义域

要求所有 Safari 用户更改其跨站点跟踪浏览器设置的替代方法是设置自定义域。自定义域与调用“闪电输出”应用的外部服务器的第一级域匹配。这种方法会导致浏览器将外部服务器和 Lightning Out 应用程序视为同一域的一部分,因此可以在两个站点之间共享 Cookie。

例如,要从服务器调用 Lightning Out 应用程序,请在 Salesforce 中添加自定义域,例如 。您必须设置 DNS 记录以将完全限定域名 (FQDN) 映射到 Salesforce 中的自定义域 URL。external.example.comlightningout.example.comlightningout.example.com

  1. 确定自定义域名,例如 .自定义域必须解析为与调用 Lightning Out 应用程序的第三方站点相同的父域。lightningout.example.com
  2. 通过输入“快速查找”框,从“设置”中查找 18 个字符的组织 ID,然后选择“域”。单击“添加域”,并记下页面顶部列出的组织 ID。Domains
  3. 使用 DNS 提供商设置 CNAME 记录,以将自定义域名(例如 )映射到 Salesforce 中的自定义域。CNAME 记录的目标使用格式 ,其中 是您在第一步中选择的自定义域名。lightningout.example.comYourFQDN.Your18charOrgId.live.siteforce.comYourFQDN
  4. 通过完成“添加域”页创建自定义域。
    1. 对于 Domain Name (域名),输入您在第一步中选择的自定义域名,例如 。lightningout.example.com
    2. 对于 HTTPS 选项,选择 Salesforce 使用您的 HTTPS 证书在 Salesforce 的服务器上通过 HTTPS 提供域。
  5. 在外部服务器页面上配置闪电输出标记,以使用 CNAME 记录的 FQDN,例如 ,这是您使用 DNS 提供商设置的。标记中的属性和函数中的参数都必须使用 CNAME 记录的 FQDN。lightningout.example.comsrcscriptlightningEndPointURI$Lightning.use()
  6. 如果您的应用使用身份验证,请参阅闪电输出身份验证。

闪电输出依赖项

创建一个特殊的独立 Aura 依赖项应用程序来描述要使用 Lightning Out 部署的组件。

一个独立的 Aura 依赖项应用只是一个具有一些属性的依赖项,以及使用标签描述的依赖组件。独立的 Aura 依赖项应用程序并不是您真正部署为供人们直接使用的应用程序的应用程序。独立的 Aura 依赖项应用仅用于指定 Lightning Out 的依赖项。<aura:application><aura:dependency>

此独立的 Aura 依赖项应用程序使用默认命名空间中的 Lightning Web 组件。myAppComponentc

<aura:application access="GLOBAL" extends="ltng:outApp">
    <aura:dependency resource="c:myAppComponent"/>
</aura:application>

注意

要在 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 src="https://myDomainName.my.salesforce.com/lightning/lightning.out.js"></script>

重要

使用主机的自定义域。不要从示例源代码中复制和粘贴其他人的实例。如果这样做,则每当 Salesforce 实例与从中加载 Lightning Out 库的实例之间存在版本不匹配时,您的应用程序就会中断。在Salesforce的定期升级期间,这种情况每年至少发生三次。别这样!

加载和初始化 Lightning 组件应用程序

使用该函数加载并初始化 Lightning 组件框架和独立的 Aura 依赖项应用程序。$Lightning.use()

该函数有四个参数。$Lightning.use()

名字类型描述
appName字符串必填。独立 Aura 依赖项应用的名称,包括命名空间。例如。"c:expenseAppDependencies"
callback功能在 Lightning 组件框架和应用程序完全加载后调用的函数。回调不接收任何参数。此回调通常是你调用将应用添加到页面的位置(请参阅下一节)。还可以通过其他方式更新显示内容,或者以其他方式响应依赖项应用准备就绪。$Lightning.createComponent()
lightningEndPointURI字符串Salesforce 实例上 Lightning 域的 URL。例如。https://myDomainName.lightning.force.com
authToken字符串有效、活动 Salesforce 会话的会话 ID 或 OAuth 访问令牌。您必须在自己的代码中获取此令牌。Lightning Out 不会为您处理身份验证。请参阅闪电输出的身份验证。

appName是必需的。其他三个参数是可选的。通常,您需要提供所有四个参数。

注意

您不能在一个页面上使用多个独立的 Aura 依赖项应用。可以多次调用,但必须在每次调用中引用相同的依赖项应用。$Lightning.use()

将 Lightning Web 组件添加到页面

使用该功能在页面上添加并激活您的组件。$Lightning.createComponent()

该函数有四个参数。$Lightning.createComponent()

名字类型描述
componentName字符串必填。要添加到页面的 Lightning Web 组件的名称,包括命名空间。例如。"c:newExpenseForm"
attributes对象必填。创建组件时要在组件上设置的属性。例如。如果组件不需要任何属性,请传入一个空对象 .{ name: theName, amount: theAmount }{ }
domLocator元素或字符串必填。指示在页面上插入所创建组件的位置的 DOM 元素或元素 ID。
callback功能在组件添加到页面并在页面上处于活动状态后调用的函数。回调接收创建的组件作为其唯一参数。

注意

您可以向一个页面添加多个 Lightning Web 组件。也就是说,您可以使用多个 DOM 定位器多次调用,以将组件添加到页面的不同部分。以这种方式创建的每个组件都必须在页面的独立 Aura 依赖项应用中指定。$Lightning.createComponent()

在幕后,调用 Aura 中的标准函数。除了 DOM 定位器之外,参数是相同的。除了将调用包装在一些 Lightning Out 语义中之外,行为也是相同的。$Lightning.createComponent()$A.createComponent()

来自 Lightning Out 的身份验证

要处理身份验证,您必须在初始化 Lightning Out 应用程序时手动提供 Salesforce 会话 ID 或身份验证令牌。

有两种受支持的方式来获取用于闪电输出的身份验证令牌。

  • 在 Visualforce 页面上,您可以使用表达式 获取当前 Visualforce 会话 ID。使用会话 ID 启动的会话只能在 Visualforce 页面上使用。{! $Api.Session_ID }
  • 在其他地方,使用 OAuth 获取经过身份验证的会话,其过程与获取用于 REST API 的经过身份验证的会话的过程相同。在这种情况下,您将获得 OAuth 令牌,并且可以在任何地方使用它。

重要

Lightning Out 不会自动为您处理身份验证。该函数只是将您提供的任何身份验证令牌传递给安全子系统。对于大多数组织,令牌是会话 ID 或 OAuth 令牌。$Lightning.use()

Lightning Out 具有与您从中获取身份验证令牌的会话相同的权限。对于 Visualforce 使用,会话具有当前用户的权限。对于 OAuth,它是定义 OAuth 连接应用时使用的任何 OAuth 范围设置。通常,将 Lightning Out 与 OAuth 结合使用需要向返回 OAuth 令牌的连接应用程序授予“完全访问权限”范围。{! $Api.Session_ID }

当使用会话访问令牌授予经过 Lightning Out 身份验证的会话时,该会话将保留对活动浏览器会话中运行的任何域的访问。用户使用有效的访问令牌登录后,将在活动浏览器会话中运行的所有 Salesforce 应用程序中验证会话凭据。lightning.force.com

为了防止会话持久性,Salesforce 管理员可以将会话锁定到原始 IP 地址。要选择此选项,请导航到:

设置>安全>会话设置

激活“将会话锁定到会话源自的 IP 地址”复选框。

与未经身份验证的用户共享 Lightning Out 应用程序

将界面添加到您的独立 Aura 依赖项应用程序,使其可供用户使用,而无需他们向 Salesforce 进行身份验证。通过此界面,您可以使用 Lightning Web 组件构建应用程序,并将其部署到任何地方和任何人。ltng:allowGuestAccess

注意

如果用户已通过 Lightning Out 端点进行身份验证,则必须在 中设置会话。尽管我们谈论的是未经身份验证的用户,但如果用户已通过身份验证,了解要求也很重要。$Lightning.use()

用法

您可以将带有界面的独立 Aura 依赖项应用程序添加到 Visualforce 页面,也可以将其与托管在 Salesforce 外部的 Lightning Out 应用程序一起使用。ltng:allowGuestAccess

  • 使用适用于 Visualforce 的 Lightning Web 组件,您可以将依赖项应用程序添加到 Visualforce 页面,然后在 Salesforce 选项卡 + Visualforce 站点中使用该页面。然后,您可以允许公众访问该页面。
  • 使用 Lightning Out,您可以在支持 Lightning Out 的任何地方部署依赖项应用程序,这几乎是任何地方!

该界面仅在启用了数字体验的组织中可用,并且您的 Lightning Out 应用程序与您在组织中定义的所有站点终结点相关联。ltng:allowGuestAccess

重要

当您通过添加界面使依赖项应用程序可供访客用户访问时,无论该站点是否启用了公共访问,都可以通过组织中的每个 Experience Cloud 站点访问该应用程序。您无法阻止通过站点 URL 访问它,也无法使其可用于某些网站,而不适用于其他网站。ltng:allowGuestAccess

注意

对于为访客访问打开的应用,请格外小心。启用访客访问的应用程序会绕过您为站点的访客用户配置文件设置的对象级和字段级安全性 (FLS)。当您引用或检索对象时,组件不会在 Apex 方法中自动强制执行 CRUD 和 FLS。该框架继续显示用户没有 CRUD 访问权限和 FLS 可见性的记录和字段。启用来宾访问的应用中使用的代码错误可能会向全世界开放组织的数据。

示例:允许访客访问 Lightning Out 应用程序

将界面添加到独立的 Aura 依赖项应用。ltng:allowGuestAccess

<aura:application access="GLOBAL" extends="ltng:outApp"
    implements="ltng:allowGuestAccess">

    <aura:dependency resource="c:storeLocatorMain"/>

</aura:application>

注意

只能将接口添加到依赖项应用,而不能添加到单个组件。ltng:allowGuestAccess

接下来,将 Lightning Out JavaScript 库添加到您的页面。

  • 使用适用于 Visualforce 的 Lightning Web 组件,只需在页面上的任意位置添加标签即可。<apex:includeLightning />
  • 借助 Lightning Out,使用站点终结点 URL 添加直接引用库的标记。<script><script src="https://YOURSITEDOMAIN/SITEURL/lightning/lightning.out.js"></script>例如:https://universalcontainers.force.com/ourstores/lightning/lightning.out.js

最后,添加 JavaScript 代码以加载和激活依赖项应用。此代码是标准的 Lightning Out,但重要的补充是,您必须将组织的站点 URL 之一用于端点。终结点 URL 采用 的格式,如本示例所示。https://YOURSITEDOMAIN/SITEURLhttps://universalcontainers.force.com/ourstores/

<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

若要避免自己的组件出现此问题,请明确其依赖项。用于引用未嵌入组件本身的所有必需静态资源。@salesforce/resourceUrl

如果您在应用程序中使用标准组件,则在 Lightning Out 或 Lightning Web Components for Visualforce 中使用它们时,它们可能没有完全样式或行为与文档中所述。

“组件库”中的“组件引用”为每个组件都有一个“体验”字段,其中列出了组件支持的容器。

为 Pardot 电子邮件内容生成器创建组件

电子邮件内容生成器中的自定义组件允许营销人员和经理为其客户创建更具吸引力的电子邮件内容。

为电子邮件生成器配置组件

在 Pardot 电子邮件内容生成器中提供自定义 Lightning Web 组件,用户可以将其添加到他们的电子邮件内容中。

在组件的配置文件中,添加电子邮件内容生成器的目标。设置为 。lightningStatic__Email<isExposed>true

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
  <apiVersion>53.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
    <target>lightningStatic__Email</target>
    <target>lightning__HomePage</target>
  </targets>
</LightningComponentBundle>

目标将属性添加到组件中。添加到组件的属性包括 、 、 、 和 。访问组件模板中的属性。lightningStatic__EmailBooleanColorIntegerStringHorizontalAlignmentVerticalAlignment

<template>
  <table …>
    <tr valign={valign}>
      <td>{content}</td>
    </tr>
  </table>
</template>

在组件文件中声明属性,如垂直对齐示例。js-meta.xml

// sampleCustomComponent.js-meta.xml
<targetConfigs>
  <targetConfig targets="lightningStatic__Email">
    <property name="buttonAlignment" type="VerticalAlignment" default="middle" />
    <designLayout>
      <designSection name="...">
        <designLayoutItems>
          <designLayoutProperty name="buttonAlignment" />
        </designLayoutItems>
      </designSection>
    </designLayout>
  </targetConfig>
</targetConfigs>

在项目目录中使用以下命令为自定义组件准备元数据包。创建的文件夹名称为 。custompackage

sf project convert source -d custompackage

将包部署到测试组织。首先,通过登录到要部署包的任意组织来创建别名。使用以下命令登录并命名别名。

sf org login web -r http://login.salesforce.com -a isvorg

使用以下命令将包部署到您授权的别名。

sf project deploy --metadata-dir -d custompackage -u isvorg

您可以通过登录到部署的目标组织来验证部署是否已完成。在“设置”的“快速查找”框中,输入 ,然后选择“部署状态”。Deployment Status

自定义组件已部署。在“设置”的“快速查找”框中,输入 ,然后选择 Lightning 组件Lightning Components

测试目标组织中的组件,以验证自定义组件是否可以在电子邮件内容生成器中使用。

自定义组件的注意事项

在 Lightning 应用程序生成器中工作的某些自定义组件与电子邮件内容生成器不兼容。在启用现有自定义组件以在电子邮件构建器中使用它们之前,请查看这些组件的要求。

不支持的项目

为我们的内容构建器提供支持的渲染引擎在安全的环境中运行。但是,在自定义组件文件中可以添加的代码存在限制。

  • 任何类型的 DOM API
  • 文件中的生命周期挂钩renderedCallback().js
  • 文件中的 Web API 方法fetch().js
  • <script>标记.html
  • 对文件中对象的引用window.js
  • 命名空间中的基本组件lightning
  • 使用语法的线路服务@wire
  • Apex 方法,但PicklistEntry

CSS 文件

  • 不支持 SLDS 令牌和选择器。:host
  • 我们建议您使用唯一的类名或在 CSS 类名前面加上命名空间,以区别于其他组件。

选择列表

  • 通过使用 Apex 创建 HTML 标记来填充选择列表。请参阅 Apex 参考指南 PicklistEntry 类。
  • 仅当覆盖以下方法时,用作选择列表数据源的 Apex 外部标注才有效:global override Boolean isValid(Object attributeValue){return true;}

向组件添加自定义 HTML

您可以将自定义 HTML 添加到组件中,以便在电子邮件内容构建器中使用。

在模板标记中指定要位于 innerHTML 容器中的元素的特殊属性和值:.ishtmlcontainer="true"

不要在其他地方使用,因为它不会处理生成 HTML 的时间。renderedCallback()

在模板中,将属性和值附加到要指定 innerHTML 容器的位置。ishtmlcontainer="true"

<template>
  <div ishtmlcontainer="true" lwc:dom="manual"></div>
</template>

在 JavaScript 文件中,为属性创建 setter 和 getter。暂时将它们留空。htmlValue

@api
set htmlValue(value) {

}

get htmlValue() {

}

添加一个方法,在该方法中创建一个实例变量,以保存对保存 innerHTML 属性的元素的引用(称为 )。在该元素的 innerHTML 属性上,为其分配刚创建的属性的值。renderedCallback()attachmentPoint

renderedCallback() {
    this.attachmentPoint = this.template.querySelector('div[ishtmlcontainer=true]');
    this.attachmentPoint.innerHTML = this.htmlValue;
}

在 setter 中,添加对所创建的实例变量的赋值的检查。将新值分配给实例变量的 innerHTML 属性,并将该值分配给非公共属性。在 getter 中,返回非公共属性的值。

import { LightningElement, api } from "lwc";

export default class CustomInner extends LightningElement {
  @api
  set htmlValue(value) {
    if (this.attachmentPoint) {
      this.attachmentPoint.innerHTML = value;
    }
    this._htmlValue = value;
  }

  get htmlValue() {
    return this._htmlValue;
  }

  renderedCallback() {
    this.attachmentPoint = this.template.querySelector("div[ishtmlcontainer=true]");
    this.attachmentPoint.innerHTML = this.htmlValue;
  }
}

在文件中定义属性的默认值和其他属性。.js-meta.xml

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="CustomInner">
    <apiVersion>53.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Custom Inner HTML</masterLabel>
    <description>Display HTML-enhanced text</description>
    <targets>
        <target>lightningStatic__Email</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightningStatic__Email">
            <property name="htmlValue" type="String" required="true" default="YOUR CUSTOM INNER HTML HERE"/>
            ...
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

为 CRM Analytics 仪表板配置组件

使用 Lightning Web 组件实现自定义功能,然后将它们与 CRM Analytics 仪表板小组件和步骤交互使用。

1. 在配置文件中添加 CRM Analytics 目标

componentName.js-meta.xml 文件定义组件的元数据值,包括允许在 CRM Analytics 仪表板中使用的设置。将目标添加到组件的配置文件中。确保将属性设置为 ,以便组件对 CRM Analytics 设计器 UI 可见。analytics__DashboardisExposedtrue

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <isExposed>true</isExposed>
    <targets>
        <target>analytics__Dashboard</target>
    </targets>
</LightningComponentBundle>

2. 设置组件配置选项

在 componentName.js-meta.xml 文件中,为目标添加 a。如果组件设计为使用仪表板步骤中的 CRM Analytics 查询数据,则将标记设置为。对于设计用于 CRM Analytics 仪表板的每个组件属性,添加标记。targetConfiganalytics__DashboardhasSteptrueproperty

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <targetConfig targets="analytics__Dashboard">
        <hasStep>true</hasStep>
        <property name="title" type="String" label="Title" description="Component Title" required="true" />
    </targetConfig>
</LightningComponentBundle>

除了常见的数据类型外,目标还支持具有 的组件的数据类型。仪表板编辑器能够从附加步骤的结果中选择给定数据类型的列。analytics__DashboardMeasureDimension<hasStep>true</hasStep>

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <targetConfig targets="analytics__Dashboard">
        <hasStep>true</hasStep>
        <property name="labelColumn" type="Dimension" label="Label Column" description="Segment Label" required="true" />
    </targetConfig>
</LightningComponentBundle>

完成这些步骤后,在 CRM Analytics Studio 仪表板编辑器中将 Lightning Web 组件添加为组件小部件。有关详细信息,请参阅《CRM Analytics 仪表板中的 Lightning Web 组件开发人员指南》。

使用 Lightning Message Service 跨 DOM 进行通信

使用 Lightning 消息服务在 Lightning 页面内的 DOM 之间进行通信。在同一 Lightning 页面中嵌入的 Visualforce 页面、Aura 组件和 Lightning Web 组件(包括实用程序栏中的组件和弹出式实用程序)之间进行通信。选择组件是订阅来自整个应用程序的消息,还是仅订阅来自活动区域的消息。

如果您要从 Salesforce Classic 切换到 Lightning Experience,则可以构建与现有 Visualforce 页面或 Aura 组件进行通信的 Lightning Web 组件。您还可以使用 Lightning 消息服务通过 Open CTI 与软件电话进行通信。

重要

Lightning 消息服务在 Lightning Experience 和 Experience Builder 站点中使用的 Lightning 组件中可用。

创建消息通道

要创建 Lightning 消息通道,请使用 LightningMessageChannel 元数据类型。

在组织中定义消息通道元数据

要将 LightningMessageChannel 部署到您的组织中,请创建一个 SFDX 项目。在目录中包括 XML 定义。LightningMessageChannel 文件名遵循以下格式。force-app/main/default/messageChannels/messageChannelName.messageChannel-meta.xml

有关元数据文件的示例,请参阅元数据 API 开发人员指南:LightningMessageChannel。

要将其添加到临时组织,请运行 。sf project deploy start

要将其添加到其他类型的组织(如沙盒或 Developer Edition 组织),请运行 。sf project deploy start

导入消息通道

以下是导入 Lightning 消息通道的方法,组件可以使用该通道通过 Lightning 消息服务进行通信。

// Syntax
import channelName from "@salesforce/messageChannel/channelReference";
// Syntax for resources in a managed package
import channelName from "@salesforce/messageChannel/namespace__channelReference";
// Example
import recordSelected from "@salesforce/messageChannel/Record_Selected__c";
  • channelName– 用于标识消息通道的导入符号。
  • channelReference– 消息通道的 API 名称。
  • namespace– 如果消息通道位于受管软件包中,则此值为受管软件包的名称空间。如果消息通道不在托管包中,请不要包含命名空间。

注意

Record_Selected__c指 LightningMessageChannel 元数据类型的自定义实例。尽管它使用后缀,但它不是自定义对象。__c

定义邮件服务的作用域

Lightning 消息服务允许您定义订阅组件在应用程序中接收消息的范围。您可以将范围限制为应用程序的活动区域,也可以将范围设置为整个应用程序。

重要

对于 Lightning Web 组件,范围功能仅在使用 时可用。@wire(MessageContext)

应用程序的活动区域包括选定的导航选项卡和项目、实用程序项目和 ES6 库。实用程序项目始终处于活动状态。导航选项卡和项目包括:

  • 标准导航选项卡
  • 控制台导航工作区选项卡
  • 控制台导航子选项卡
  • 控制台导航项

要从应用程序中的任何位置接收消息通道上的消息,请从 导入。然后,调用并传递可选的第四个参数。APPLICATION_SCOPElightning/messageServicesubscribe(){ scope: APPLICATION_SCOPE }subscriberOptions

// Import message service features.
import {
    subscribe,
    unsubscribe,
    APPLICATION_SCOPE,
    MessageContext
} from 'lightning/messageService';

// To pass scope, you must get a message context.
@wire(MessageContext)
    messageContext;

// Pass scope to the subscribe() method.
    subscribeToMessageChannel() {
        if (!this.subscription) {
            this.subscription = subscribe(
                this.messageContext,
                recordSelected,
                (message) => this.handleMessage(message),
                { scope: APPLICATION_SCOPE }
            );
        }
    }

从活动区域接收消息是默认行为。无需包含 scope 属性即可将范围限制为活动区域。

在消息通道上发布

要从 Lightning Web 组件在消息通道上发布消息,请在组件的 JavaScript 文件中包含作用域模块,并调用 Lightning 消息服务的函数。@salesforce/messageChannelpublish()

Lightning 消息服务将消息发布到任何订阅的组件,直到组件生命周期的销毁阶段。有时,当您离开 Lightning 页面时,组件会被缓存而不是销毁。如果 Lightning 消息服务的范围限定为整个应用程序,则这些组件仍会向 Lightning 消息服务发布消息并从 Lightning 消息服务接收消息。

提示

lwc-recipes 存储库有一个组件,用于在 Lightning 页面上发布消息以通知订阅者。Lightning 消息服务在页面上的 Visualforce、Aura 和 Lightning Web 组件之间传达该消息。lmsPublisherWebComponent

让我们看一下 lmsPublisherWebComponent 组件。组件的 HTML 模板文件显示联系人列表。选择联系人后,将调用处理程序,该处理程序将消息发布到消息通道。handleContactSelect

<!-- lmsPublisherWebComponent.html -->
<template>
  <lightning-card title="LMSPublisherWebComponent" icon-name="custom:custom30">
    <div class="slds-m-around_medium" oncontactselect={handleContactSelect}>
      <template lwc:if={contacts.data}>
        <template for:each={contacts.data} for:item="contact">
          <c-contact-list-item-bubbling
            key={contact.Id}
            contact={contact}>
          </c-contact-list-item-bubbling>
        </template>
      </template>
    </div>
  </lightning-card>
</template>

在组件的 JavaScript 文件中,导入使用消息通道所需的消息通道和 Lightning 消息服务函数。

// lmsPublisherWebComponent.js
import { LightningElement, wire } from "lwc";
import getContactList from "@salesforce/apex/ContactController.getContactList";

// Import message service features required for publishing and the message channel
import { publish, MessageContext } from "lightning/messageService";
import recordSelected from "@salesforce/messageChannel/Record_Selected__c";

export default class LmsPublisherWebComponent extends LightningElement {
  @wire(getContactList)
  contacts;

  @wire(MessageContext)
  messageContext;

  // Respond to UI event by publishing message
  handleContactSelect(event) {
    const payload = { recordId: event.target.contact.Id };

    publish(this.messageContext, recordSelected, payload);
  }
}

用于创建一个对象,该对象提供有关使用 Lightning 消息服务的 Lightning Web 组件的信息。使用适配器时,您不必与组件的任何生命周期事件进行交互。当组件被销毁时,Lightning 消息服务功能会自动注销。@wire(MessageContext)MessageContext@wire(MessageContext)

该方法创建要发布的消息内容。闪电消息服务的函数采用三个参数:消息上下文、消息通道名称和消息有效负载。在这里,消息有效负载是一个 JSON 对象,其中键的值为 。handleContactSelect()publish()recordIdevent.target.contact.Id

注意

组件必须附加到 DOM,然后才能使用用 修饰的属性。不能在函数中使用。@wire(MessageContext)@wire(MessageContext)constructor()

订阅和取消订阅消息通道

要订阅和取消订阅消息通道上的消息,请将消息通道从作用域模块导入到 Lightning Web 组件中。调用 Lightning 消息服务和函数。@salesforce/messageChannelsubscribe()unsubscribe()

提示

lwc-recipes 存储库有一个组件,用于显示如何订阅和取消订阅消息通道。此示例适用于“在消息通道上发布”中的发布者组件。lmsSubscriberWebComponent

让我们看一下 lmsSubscriberWebComponent 组件。从发布者组件中选择联系人会将所选记录 ID 发布到消息通道。Record_Selected__c

订阅者组件的 HTML 对已发布的消息做出反应,并显示其记录 ID 通过消息负载提供的联系人的数据。

<!-- lmsSubscriberWebComponent.html -->
<template>
  <lightning-card title="LMSSubscriberWebComponent" icon-name="custom:custom30">
    <div class="slds-m-around_medium">
      <template lwc:if={Picture__c}>
        <img src={Picture__c} alt="Profile photo" />
      </template>
      <p>{Name}</p>
      <p>{Title}</p>
      <p>
        <lightning-formatted-phone value={Phone}></lightning-formatted-phone>
      </p>
      <p>
        <lightning-formatted-email value={Email}></lightning-formatted-email>
      </p>
    </div>
  </lightning-card>
</template>

在组件的 JavaScript 中,导入从 订阅所需的消息服务功能。从 导入消息通道。lightning/messageServiceRecord_Selected__c@salesforce/messageChannel

用于创建 Context 对象,该对象提供有关使用 Lightning 消息服务的 Lightning Web 组件的信息。组件必须附加到 DOM,然后才能使用用 修饰的属性。@wire(MessageContext)@wire(MessageContext)

该函数检查是否为 null。如果订阅为 null,则调用 Lightning 消息服务的方法并将其分配给 。该方法采用三个必需的参数:消息上下文、消息通道的名称以及处理已发布消息的侦听器方法。调用侦听器方法时,它会将消息传递给 。 从它收到的 JSON 消息有效负载中提取属性。然后,使用与记录 ID 匹配的联系人相关的信息更新 HTML 模板。subscribeToMessageChannel()subscriptionsubscribe()subscriptionsubscribe()handleMessage()handleMessage()recordId

若要从应用程序中的任何位置接收消息通道上的消息,请将该方法的第四个参数作为可选参数传递。请参阅定义邮件服务的作用域。{ scope: APPLICATION_SCOPE }subscribe()

要停止接收来自 Lightning 消息服务的消息,请调用 ,传入订阅引用。该对象包含对要取消订阅的订阅的引用。此示例调用 ,后者调用 ,然后设置为 null。unsubscribe()subscriptionunsubscribeToMessageChannel()unsubscribe()subscription

// lmsSubscriberWebComponent.js
import { LightningElement, wire } from "lwc";
import { getRecord, getFieldValue } from "lightning/uiRecordApi";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { reduceErrors } from "c/ldsUtils";

// Import message service features required for subscribing and the message channel
import {
  subscribe,
  unsubscribe,
  APPLICATION_SCOPE,
  MessageContext,
} from "lightning/messageService";
import recordSelected from "@salesforce/messageChannel/Record_Selected__c";

import NAME_FIELD from "@salesforce/schema/Contact.Name";
import TITLE_FIELD from "@salesforce/schema/Contact.Title";
import PHONE_FIELD from "@salesforce/schema/Contact.Phone";
import EMAIL_FIELD from "@salesforce/schema/Contact.Email";
import PICTURE_FIELD from "@salesforce/schema/Contact.Picture__c";

const fields = [NAME_FIELD, TITLE_FIELD, PHONE_FIELD, EMAIL_FIELD, PICTURE_FIELD];

export default class LmsSubscriberWebComponent extends LightningElement {
  subscription = null;
  recordId;

  Name;
  Title;
  Phone;
  Email;
  Picture__c;

  @wire(getRecord, { recordId: "$recordId", fields })
  wiredRecord({ error, data }) {
    if (error) {
      this.dispatchToast(error);
    } else if (data) {
      fields.forEach((item) => (this[item.fieldApiName] = getFieldValue(data, item)));
    }
  }

  @wire(MessageContext)
  messageContext;

  // Encapsulate logic for Lightning message service subscribe and unsubsubscribe
  subscribeToMessageChannel() {
    if (!this.subscription) {
      this.subscription = subscribe(
        this.messageContext,
        recordSelected,
        (message) => this.handleMessage(message),
        { scope: APPLICATION_SCOPE },
      );
    }
  }

  unsubscribeToMessageChannel() {
    unsubscribe(this.subscription);
    this.subscription = null;
  }

  // Handler for message received by component
  handleMessage(message) {
    this.recordId = message.recordId;
  }

  // Standard lifecycle hooks used to subscribe and unsubsubscribe to the message channel
  connectedCallback() {
    this.subscribeToMessageChannel();
  }

  disconnectedCallback() {
    this.unsubscribeToMessageChannel();
  }

  // Helper
  dispatchToast(error) {
    this.dispatchEvent(
      new ShowToastEvent({
        title: "Error loading contact",
        message: reduceErrors(error).join(", "),
        variant: "error",
      }),
    );
  }
}

注意

如果创建的服务组件不是 ,则不能用于创建对象。而是从 import 和 methods。用于创建 Context 对象并将其分配给字段,如 .然后,传入方法。不会自动为服务组件发布上下文。调用以删除与组件的消息上下文关联的任何订阅。LightningElement@wire(MessageContext)MessageContextcreateMessageContext()releaseMessageContext()lightning/messageServicecreateMessageContext()messageContextmessageContextsubscribe()releaseMessageContext(messageContext)

Lightning 消息服务限制

使用 Lightning 消息服务时,请记住以下几点。

Lightning 消息服务仅支持以下体验:

  • Lightning Experience 标准导航
  • Lightning Experience 控制台导航
  • 适用于 Aura 和 Lightning Web 组件的 Salesforce 移动应用程序,但不适用于 Visualforce 页面
  • Aura 和基于 LWR 的 Experience Builder 站点中使用的 Lightning 组件。注意Lightning 消息服务不适用于 Salesforce 选项卡 + Visualforce 站点或 Experience Builder 站点中的 Visualforce 页面。

在不支持 Lightning 消息传递服务的容器中,使用该模块。从 github.com/developerforce/pubsub 下载模块。pubsub

在 AppExchange 上发布的包中包含消息通道时,支持 1GP 和 2GP 包。

对于 Lightning Web 组件,您可以定义订阅组件仅在使用 时在应用程序中接收消息的范围。@wire(MessageContext)

使用移动设备功能

移动功能允许您在 Lightning Web 组件中使用移动设备功能。直接从您的组件代码访问摄像头和位置检测硬件,以及联系人和日历数据等平台功能。使用这些特定于移动设备的功能构建感觉像本机移动应用程序的 Lightning 应用程序。

《移动和离线开发人员指南》中提供了完整的详细信息,该指南是执行移动开发时本指南的重要配套。

显示通知

组件可以发送弹出的通知以提醒用户、请求用户确认、提示响应或仅提供信息。

警报模态

使用警报模式来停止用户,并传达影响其系统、功能或页面的紧急错误。要在 Lightning Experience 中显示警报模式,请从模块导入,然后使用所需的属性进行调用。LightningAlertlightning/alertLightningAlert.open()

注意

此警报模式是原生函数的替代方法,Chrome 和 Safari 中的跨域 iframe 不支持该函数。与本机警报函数不同,它不会停止页面上的执行,而是返回 Promise。使用 / 或 用于要在模式关闭后执行的任何代码。window.alert()LightningAlert.open()asyncawait.then()

此示例组件创建一个按钮,用于打开在屏幕截图中看到的警报模式 UI。通常,错误条件会触发警报模式的显示。

<!-- c/myApp.html -->
<template>
  <lightning-button onclick={handleAlertClick} label="Open Alert Modal"> </lightning-button>
</template>

在打开警报模式的组件的 JavaScript 文件中导入。创建并调度具有 、 和 属性的事件。该函数返回一个 promise,当您单击“确定”时,该 promise 将解析。LightningAlertlightning/alertLightningAlertmessagethemelabel.open()

// 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
  }
}

有关警报模式属性的信息,请参阅组件参考。

确认模态

使用确认模式要求用户在继续操作之前做出响应。要在 Lightning Experience 中显示确认模式,请从模块导入,然后使用所需的属性进行调用。LightningConfirmlightning/confirmLightningConfirm.open()

注意

此确认模式是原生函数的替代方法,Chrome 和 Safari 中的跨域 iframe 不支持该函数。与本机 confirm 函数不同,它不会停止页面上的执行,而是返回一个 Promise。使用 / 或 用于要在模式关闭后执行的任何代码。window.confirm()LightningConfirm.open()asyncawait.then()

此示例组件创建一个按钮,用于打开您在屏幕截图中看到的确认模式 UI。

<!-- c/myApp.html -->
<template>
  <lightning-button onclick={handleConfirmClick} label="Open Confirm Modal"> </lightning-button>
</template>

在打开确认模式的组件的 JavaScript 文件中导入。创建并调度具有 、 和 属性的事件。该函数返回一个 promise,该 promise 解析为单击“确定”和单击“取消”时。LightningConfirmlightning/confirmLightningConfirmmessagevariantlabel.open()truefalse

// 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
  }
}

有关确认模式的属性的信息,请参阅组件参考。

提示模态

使用提示模式要求用户在继续操作之前提供信息。要在 Lightning Experience 中显示提示模式,请从模块导入,然后使用所需的属性进行调用。LightningPromptlightning/promptLightningPrompt.open()

注意

此提示模式是原生函数的替代方法,Chrome 和 Safari 中的跨域 iframe 不支持该函数。与本机提示函数不同,它不会停止页面上的执行,而是返回 Promise。使用 / 或 用于要在模式关闭后执行的任何代码。window.prompt()LightningPrompt.open()asyncawait.then()

此示例组件创建一个按钮,用于打开在屏幕截图中看到的提示模式 UI。

<!-- c/myApp.html -->
<template>
  <lightning-button onclick={handlePromptClick} label="Open Prompt Modal"> </lightning-button>
</template>

在打开提示模式的组件的 JavaScript 文件中导入。创建并调度具有 、 、 和 属性的事件。如果用户输入文本并在提示中单击“确定”,则该函数将返回解析为输入值的 promise。如果用户单击“取消”,该函数将返回解析为 的 promise。LightningPromptlightning/promptLightningPromptmessagethemelabeldefaultValue.open()null

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
    });
  }
}

有关提示模式属性的信息,请参阅组件参考。

Toast 通知

组件可以发送弹出的 Toast 通知,以提醒用户成功、错误或警告。祝酒词也可以简单地提供信息。

要在 Experience Cloud 的 Lightning Experience 或 Aura 站点中显示 Toast 通知,请从模块导入。ShowToastEventlightning/platformShowToastEvent

注意

ShowToastEvent在 Aura 站点的登录页面上不受支持。 在 Experience Cloud 的 LWR 站点中也不受支持。请改用 lightning/toastContainer 模块 (Beta)。ShowToastEvent

lwc-recipes 存储库有一个组件,可用于自定义和发送 Toast,以便您可以尝试变体。

HTML 模板生成在屏幕截图中看到的 UI。

<!-- miscToastNotification.html -->
<template>
  <lightning-card title="miscToastNotification" icon-name="custom:custom19">
    <div class="slds-m-around_medium">
      <lightning-input label="Title" value={_title} onchange={titleChange}></lightning-input>
      <lightning-input
        label="Message"
        value={message}
        onchange={messageChange}>
      </lightning-input>
      <lightning-combobox
        label="Variant"
        value={variant}
        onchange={variantChange}
        options={variantOptions}>
      </lightning-combobox>
      <p class="slds-m-vertical_small">
        <lightning-button label="Show Notification" onclick={showNotification}></lightning-button>
      </p>
    </div>
  </lightning-card>
</template>

只需从 .创建和调度具有 、 、 和 属性的事件。此示例使用 的默认值 ,因此不包括在内。ShowToastEventlightning/platformShowToastEventShowToastEventtitlemessagevariantmodemode

// miscToastNotification.js
import { LightningElement } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";

export default class MiscToastNotification extends LightningElement {
  _title = "Sample Title";
  message = "Sample Message";
  variant = "error";
  variantOptions = [
    { label: "error", value: "error" },
    { label: "warning", value: "warning" },
    { label: "success", value: "success" },
    { label: "info", value: "info" },
  ];

  titleChange(event) {
    this._title = event.target.value;
  }

  messageChange(event) {
    this.message = event.target.value;
  }

  variantChange(event) {
    this.variant = event.target.value;
  }

  showNotification() {
    const evt = new ShowToastEvent({
      title: this._title,
      message: this.message,
      variant: this.variant,
    });
    this.dispatchEvent(evt);
  }
}
ShowToastEvent参数类型描述
title字符串Toast 的标题,显示为标题。
message字符串一个字符串,包含用户的消息。
messageDataString[] 或 Objecturl以及替换字符串中占位符的值。label{index}message
variant字符串Toast 中显示的主题和图标。有效值为:info—(默认)带有信息图标的灰色框。success– 带有复选标记图标的绿色框。warning– 带有警告图标的黄色框。error– 带有错误图标的红色框。您可以在 Lightning Design System 文档中查看每个主题的样式。
mode字符串确定 Toast 的持久性。有效值为:dismissible—(默认)保持可见,直到用户单击关闭按钮或 3 秒过去,以先到者为准。pester– 保持可见 3 秒。sticky– 在用户单击关闭按钮之前保持可见。

提示

要运行此代码,请将 github.com/trailheadapps/lwc-recipes 源推送到 Salesforce 组织。

导航到页面、记录和列表

要在 Lightning Experience、Experience Builder 站点和 Salesforce 移动应用程序中导航,请使用导航服务 .lightning/navigation

该服务仅在 Lightning Experience、Experience Builder 站点和 Salesforce 移动应用程序中受支持。其他容器不支持它,例如 Lightning Components for Visualforce 或 Lightning Out。即使您在 Lightning Experience 或 Salesforce 移动应用程序中访问这些容器,也是如此。lightning/navigation

基本导航

使用导航服务 导航到许多不同的页面类型,如记录、列表视图和对象。还可以使用导航服务打开文件。lightning/navigation

导航服务使用 .PageReference 是一个 JavaScript 对象,用于描述页面类型、其属性和页面状态。使用 a 可以使组件免受将来对 URL 格式的更改的影响。它还允许您的组件在多个应用程序中使用,每个应用程序都可以使用不同的 URL 格式。PageReferencePageReference

PageReference财产类型描述必填
type字符串要在 Lightning Experience、Experience Builder 站点或 Salesforce 移动应用程序中导航,请定义一个对象。该类型生成唯一的 URL 格式,并定义应用于该类型的所有页面的属性。对于 Experience Builder 站点,根据页面类型,LWR 站点和 Aura 站点之间的属性要求可能有所不同。请参见 PageReference 类型。PageReferencePageReferencePageReference是的
attributes对象确定目标页面的名称/值对的映射。页面类型定义可能的属性名称集及其各自的值类型。是的
state对象一组具有字符串键和字符串值的键值对。这些参数有条件地自定义给定页面中的内容。某些页面引用类型支持一组标准属性。还可以将非标准属性传递到只要它们具有命名空间即可。statestate

导航服务将两个 API 添加到组件的类中。由于这些 API 是类上的方法,因此请从 调用它们。this

  • [NavigationMixin.Navigate](pageReference, [replace])组件调用以导航到应用程序中的另一个页面。this[NavigationMixin.Navigate]
  • [NavigationMixin.GenerateUrl](pageReference)组件调用以获取解析为生成的 URL 的 URL。该组件可以在定位点的属性中使用 URL。它还可以使用 URL 通过浏览器 API 打开新窗口。this[NavigationMixin.GenerateUrl]promisehrefwindow.open({url})

使用导航服务

  1. 在组件的 JavaScript 类中,从 lightning/navigation 模块导入函数。NavigationMixinimport { NavigationMixin } from "lightning/navigation";
  2. 将该函数应用于组件的基类。NavigationMixinexport default class MyCustomElement extends NavigationMixin(LightningElement) {}
  3. 创建一个用于定义页面的纯 JavaScript PageReference 对象。
  4. 若要调度导航请求,请调用导航服务的函数。如果设置为 ,则替换浏览器历史记录中的现有条目,以便用户不必按两次后退按钮。缺省值为 。[NavigationMixin.Navigate]({pageReference}, [{replace}]){replace}true{pageReference}falsenavigateNext() { this[NavigationMixin.Navigate]({ type: 'standard__navItemPage', attributes: { apiName: this.tabName, }, }); }

当您使用 导航到页面引用时,例如从启用了快速操作的组件,默认情况下不会自动关闭该模式。例如,如果组件导航到记录创建页面,则包含组件的模式将保持打开状态,但处于非活动状态,而另一个模式则将其与记录创建页面覆盖。当您使用记录创建页面关闭新模式时,包含组件的先前模式将再次变为活动状态。要在导航时自动关闭上一个模式,请设置为 。[NavigationMixin.Navigate](pageReference, [replace])replacetrue

示例:导航到帐户主页

此示例显示指向帐户主页的链接。当用户单击该链接时,事件处理程序 将调用导航服务的方法,该方法将加载帐户主页。帐户主页 URL 也可在锚标记中找到,该标记允许用户复制链接或在新窗口中打开它。clickhandleClickNavigate

<!-- navigationLinkExample.html -->
<template>
  <div>
    <a href={url} onclick={handleClick}>Account Home</a>
  </div>
</template>

在组件的 JavaScript 文件中,导入导航服务。

若要导航到帐户主页并生成其 URL,导航服务使用一个对象。当组件插入到 DOM 中时,对象 在生命周期钩子中定义。导航服务将帐户主页 URL 存储在模板中使用的属性中。PageReferencePageReferenceaccountHomePageRefconnectedCallback()url

事件处理程序也在组件的 JavaScript 类中定义,并导航到页面引用 .handleClickaccountHomePageRef

// 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

使用 state 属性

使用属性时,请牢记这些行为。state

  • 对象已冻结,因此无法直接更改它。要导航到具有修改后的同一页面,请复制当前页面并使用 修改副本。PageReferencestatePageReferenceObject.assign({}, pageReference)
  • state属性必须使用命名空间前缀,后跟两个下划线。如果组件不是托管包的一部分,请使用命名空间前缀。如果组件是托管包的一部分,请使用包的命名空间。__c
  • 由于 的键值对序列化为 URL 查询参数,因此所有值都必须是字符串。PageReference.state
  • 使用值的代码必须将值分析为其正确的格式。state
  • 要从对象中删除值,请将其设置为 。stateundefined
  • 即使使用 HTTPS,在 URL 参数中包含个人数据也不安全。有关详细信息,请参阅存储敏感数据。
  • 在使用 Aura 或 LWR 模板构建的 Lightning Experience 和 Experience Builder 站点中,仅当 URL 查询字符串发生更改时,不会重新呈现视图。为了对 URL 查询字符串中的更改做出反应,我们建议组件观察该对象并与页面引用的 .CurrentPageReferencestate

示例:更新当前页面状态

此示例中的组件有一个标记为“显示面板”的链接,单击该链接时将更改为“隐藏面板”。单击任一链接都会更新当前页面的状态。当页面状态更改时,用 修饰的属性将更新。组件将重新呈现以显示或隐藏面板并更新链接标签。this.currentPageReference@wire(CurrentPageReference)

<!-- pageStateChangeExample.html -->
<template>
  <div>
    <a href={showPanelUrl} onclick={handleShowPanelClick}>Show Panel</a>
  </div>
  <div lwc:if={showPanel}>
    <h1>This is the panel</h1>
    <a href={noPanelUrl} onclick={handleNoPanelClick}>Hide Panel</a>
  </div>
</template>
// 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

<!-- navTab.html -->
<template>
  <lightning-button variant="brand" label={label} title={label} onclick={navigateNext}>
  </lightning-button>
</template>
// navTab.js
import { LightningElement, api } from "lwc";
import { NavigationMixin } from "lightning/navigation";

export default class Navtab extends NavigationMixin(LightningElement) {
  @api tabName;
  @api label;
  navigateNext() {
    this[NavigationMixin.Navigate]({
      type: "standard__navItemPage",
      attributes: {
        apiName: this.tabName,
      },
    });
  }
}

提示

lwc-recipes 存储库有很多导航示例。查看名为 的组件。nav*

更多页面类型示例

此代码显示了在 Lightning 中导航到不同类型页面的示例。这些示例演示如何创建不同类型的页面引用对象并导航到这些页面。您还可以将页面引用传递给 API,以检索解析为页面的 URL。[NavigationMixin.GenerateUrl](pageReference)promise

// 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
    );
  }
}

若要使用预填充的字段值启动记录的创建页面,请同时使用 and。lightning/pageReferenceUtilslightning/navigation

lightning/pageReferenceUtils 模块提供了 and 函数,用于将默认字段值编码为字符串并对其进行解码。将编码字符串分配给页面引用中的属性。encodeDefaultFieldValues()decodeDefaultFieldValues()pageReference.state.defaultFieldValuesstandard__objectPage

使用标准操作时,默认字段值会以字符串形式通过 URL 传递到对象,并为您处理重定向和替换。通过覆盖操作,您负责从 URL 解码默认字段值的字符串。

提示

在 lwc-recipes 示例存储库中,请参阅 navToNewRecordWithDefaults 组件。

使用标准操作启动具有默认字段值的联系人记录

此示例使用预填充的默认值启动记录的创建页。

此示例 HTML 包含用于创建联系人的链接。

<!-- navToNewRecordWithDefaults.html -->
<template>
  <lightning-button
    name="new-with-defaults"
    label="Go to New Contact with Defaults"
    class="slds-m-around_medium"
    onclick={navigateToNewContactWithDefaults}>
  </lightning-button>
</template>

要将默认字段值编码为字符串,请将它们传递给 。将编码的字符串分配给页面引用中的属性。encodeDefaultFieldValues()state.defaultFieldValues

// navToNewRecordWithDefaults.js
import { LightningElement } from "lwc";
import { NavigationMixin } from "lightning/navigation";
import { encodeDefaultFieldValues } from "lightning/pageReferenceUtils";

export default class NavToNewRecordWithDefaults extends NavigationMixin(LightningElement) {
  navigateToNewContactWithDefaults() {
    const defaultValues = encodeDefaultFieldValues({
      FirstName: "Morag",
      LastName: "de Fault",
      LeadSource: "Other",
    });

    console.log(defaultValues);

    this[NavigationMixin.Navigate]({
      type: "standard__objectPage",
      attributes: {
        objectApiName: "Contact",
        actionName: "new",
      },
      state: {
        defaultFieldValues: defaultValues,
      },
    });
  }
}

使用覆盖操作处理默认字段值

要使用自定义解决方案覆盖标准操作行为,请将模块包装在 Aura 组件中。

// auraOverrideWrapper.cmp
<aura:component implements="lightning:actionOverride">
  <c:lwcNewAccountOverride></c:lwcNewAccountOverride>
</aura:component>

该组件包括一个用于显示默认字段值的新客户记录页的窗体。lwcNewAccountOverride

<!-- lwcNewAccountOverride.html -->
<template>
  <lightning-record-edit-form object-api-name="Account" onsuccess={handleAccountCreated}>
    <lightning-input-field field-name="Name" value={dfv_AccountName}> </lightning-input-field>
    <lightning-input-field field-name="NumberOfEmployees" value={dfv_NumberOfEmployees}>
    </lightning-input-field>
    <lightning-input-field field-name="OwnerId" value={dfv_OwnerId}> </lightning-input-field>
    <lightning-input-field field-name="CustomCheckbox__c" value={dfv_CustomCheckbox}>
    </lightning-input-field>

    <lightning-button class="slds-m-top_small" type="submit" label="Create"> </lightning-button>
  </lightning-record-edit-form>
</template>

通过覆盖操作,您负责从 URL 解码默认字段值的字符串。

此示例用于从中读取默认字段值并获取编码的字符串。然后,它将字符串传递给 对其进行解码并处理帐户创建。CurrentPageReferencestatedecodeDefaultFieldValues()

此示例类似于使用 预填充字段值,不同之处在于此处的 是导航到表单时动态生成的。lightning-record-edit-formdefaultFieldValues

// lwcNewAccountOverride.js
import { LightningElement, wire } from "lwc";
import { CurrentPageReference } from "lightning/navigation";
import { decodeDefaultFieldValues } from "lightning/pageReferenceUtils";

export default class LwcNewAccountOverride extends LightningElement {
  @wire(CurrentPageReference)
  setCurrentPageReference(currentPageReference) {
    if (currentPageReference.state.defaultFieldValues) {
      const dfvObject = decodeDefaultFieldValues(currentPageReference.state.defaultFieldValues);
      this.dfv_AccountName = dfvObject.Name;
      this.dfv_NumberOfEmployees = dfvObject.NumberOfEmployees;
      // Handling required for boolean because we don't support boolean field types
      this.dfv_CustomCheckbox = dfvObject.CustomCheckbox__c === "true";
      this.dfv_OwnerId = dfvObject.OwnerId;
    }
  }

  dfv_AccountName = "";
  dfv_NumberOfEmployees = "";
  dfv_OwnerId = "";
  dfv_CustomCheckbox = false;

  // Run code when account is created
  handleAccountCreated() {}
}

重要

所有编码的默认字段值都以字符串形式传递到记录创建页面。例如,作为字符串而不是数字传递到页面中,布尔值 和 作为字符串传递。35000truefalse

若要使用此代码,请在“设置”中输入 。在 Account 对象上,创建一个具有 API 名称的复选框字段。然后选择“按钮”、“链接”和“操作”,并编辑“新建”操作。对于 Lightning Experience Override,选择 Lightning 组件,然后选择组件。Object ManagerCustomCheckbox__cc:auraOverrideWrapper

打开文件

要在 Lightning Experience 和 Salesforce 应用程序中打开一个或多个文件记录,请使用导航服务 .导航服务在 Lightning Experience 的模式对话框中打开一个或多个文件的预览,或在移动设备上的 Salesforce 应用程序中触发文件下载。lightning/navigation

使用页面引用打开文件

导航服务使用 PageReference,它描述一个页面,在本例中是一个文件。

使用带有 和 属性的页面引用。'type': 'standard__namedPage'pageNamefilePreview

命名页值支持 ContentDocument 和 ContentHubItem(外部文件)对象。Lightning Experience 和所有版本的移动应用程序都支持命名页面值。其他容器(例如 Lightning Components for Visualforce、Lightning Out 或 Experience Cloud 站点)不支持此功能。即使您在 Lightning Experience 或 Salesforce 移动应用程序中访问这些容器,页面值也不受支持。filePreviewfilePreview

示例:打开文件记录

此示例在 Lightning Experience 和 Salesforce 应用程序中打开带有 ID 的记录。069xx0000000001AAA

<!-- openFileSample.html -->
<template>
  <div>
    <a onclick={navigateToFiles}>Navigate To Files</a>
  </div>
</template>
// openFileSample.js
import { LightningElement } from "lwc";
import { NavigationMixin } from "lightning/navigation";

export default class OpenFileSample extends NavigationMixin(LightningElement) {
  navigateToFiles() {
    this[NavigationMixin.Navigate]({
      type: "standard__namedPage",
      attributes: {
        pageName: "filePreview",
      },
      state: {
        recordIds: "069xx0000000001AAA,069xx000000000BAAQ",
        selectedRecordId: "069xx0000000001AAA",
      },
    });
  }
}

该属性是可供下载的所有记录 ID 的逗号分隔列表。recordIds

在 Lightning Experience 中,首先下载中指定的记录。用户可以通过单击应用程序中的箭头切换到其他记录。桌面文件预览器提供基于图像和 SVG 的多页办公文档预览、演示模式以及对文件操作(如共享、下载、上传和删除)的快速访问。selectedRecordId

在 Salesforce 应用程序中,触发事件时会下载单个文件。如果指定,则下载该文件。如果未指定,则下载列表中的第一个文件。根据设备的不同,将显示文件的本机预览。selectedRecordIdselectedRecordIdrecordIds

在 Visualforce Pages 中使用组件

将 Lightning Web 组件添加到您的 Visualforce 页面,以利用您在 Visualforce 中所做的任何投资。使用 Lightning Web 组件实现新功能,然后将其用于现有 Visualforce 页面。

重要

Lightning Components for Visualforce 基于 Lightning Out,这是一项强大而灵活的功能,可让您将 Aura 和 Lightning Web 组件嵌入到几乎任何网页中。当与 Visualforce 一起使用时,一些细节变得更加简单。例如,无需处理身份验证,也无需配置连接的应用。

在其他方面,使用 Visualforce 的 Lightning 组件就像使用 Lightning Out 一样。有关详细信息,请参阅闪电输出。

将 Lightning Web 组件添加到 Visualforce 页面有三个步骤。

步骤 1:添加 Visualforce JavaScript 库的 Lightning 组件

在 Visualforce 页面的开头添加。此组件加载 Lightning Components for Visualforce 使用的 JavaScript 文件。<apex:includeLightning/>

步骤 2:创建并引用独立的 Aura 依赖项应用

创建独立的 Aura 依赖项应用。使应用程序可全局访问并扩展 .声明对它使用的任何 Lightning 定义(如组件)的依赖关系。ltng:outApp

此示例 Aura 依赖项应用使用 Aura 标记来指示它使用标准 Lightning 组件 。<aura:dependency>lightning:button

<!--lwcvf.app-->
<aura:application access="GLOBAL" extends="ltng:outApp">
  <aura:dependency resource="lightning:button" />
</aura:application>

为您使用的每个 Lightning Web 组件添加一个标签。使用命名约定引用自定义 Lightning Web 组件。<aura:dependency><namespace:camelCaseComponentName>

注意

扩展范围会将 SLDS 资源添加到页面,以允许您的组件使用 Salesforce Lightning 设计系统 (SLDS) 进行样式设置。如果您不希望将 SLDS 资源添加到页面中,请改为从ltng:outAppltng:outAppUnstyled

若要在 Visualforce 页面上引用此应用程序,请使用以下 JavaScript 代码,其中 theNamespace 是应用程序的命名空间前缀。也就是说,您组织的命名空间,或提供应用程序的托管包的命名空间。

$Lightning.use("theNamespace:lwcvf", function () {});

如果应用是在组织中定义的(即,不在托管包中),请改用默认命名空间,如下例所示。如果您的组织未定义命名空间,则必须使用默认命名空间。c

有关创建 Lightning 依赖项应用程序的更多详细信息,请参阅 Lightning Out 依赖项。

步骤 3:在 Visualforce 页面上创建组件

最后,使用 将顶级组件添加到页面。$Lightning.createComponent(String type, Object attributes, String domLocator, function callback)

让我们看一个示例 Visualforce 页面,该页面使用上一个示例中的 创建。lightning:buttonlwcvf.app

<apex:page>
    <apex:includeLightning />

    <div id="lightningvf" />

    <script>
        $Lightning.use("c:lwcvf", function() {
          $Lightning.createComponent("lightning:button",
              { label : "Press Me!" },
              "lightningvf",
              function(cmp) {
                console.log("button was created");
                // do some stuff
              }
          );
        });
    </script>
</apex:page>

该调用将创建一个带有“Press Me!”标签的按钮。该按钮入到 ID 为 的 DOM 元素中。在页面上添加按钮并处于活动状态后,将调用回调函数并执行语句。回调接收创建的组件作为其唯一参数。在这个简单示例中,该按钮未配置为执行任何操作。$Lightning.createComponent()lightningvfconsole.log()

重要

您可以在一个页面上多次调用,但所有调用都必须引用同一个独立的 Aura 依赖项应用。$Lightning.use()

有关使用 和 的更多详细信息,请参阅闪电输出标记。$Lightning.use()$Lightning.createComponent()

浏览器第三方 Cookie

Lightning 组件在用户的浏览器中设置 Cookie。由于 Lightning 组件和 Visualforce 由不同的域提供,因此这些 Cookie 是“第三方”Cookie。您的用户必须在其浏览器设置中允许第三方 Cookie。有关更多详细信息,包括在 Safari 中禁用“阻止跨站点跟踪”设置的要求,请参阅闪电输出要求。

自定义选项卡

您可以将 Lightning Web 组件添加为 Lightning Experience 或 Salesforce 移动应用程序中的自定义选项卡。

为自定义选项卡配置组件

要将 Lightning Web 组件用作 Lightning Experience 或 Salesforce 移动应用程序中的自定义选项卡,请在组件的配置文件中添加选项卡目标。

componentName.js-meta.xml 文件定义组件的元数据值,包括允许在自定义选项卡中使用设置。将目标添加到组件的配置文件中。lightning__Tab

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
   <targets>
     <target>lightning__Tab</target>
  </targets>
</LightningComponentBundle>

配置选项卡目标后,将 Lightning Web 组件添加为 Lightning Experience 或 Salesforce 移动应用程序中的自定义选项卡。

在 Lightning Experience 应用程序中将组件添加为自定义选项卡

在自定义选项卡中提供 Lightning Web 组件,以便在桌面和 Salesforce 移动应用程序的 Lightning Experience 中访问该组件。

要配置要用作自定义选项卡的 Lightning Web 组件,请参阅为自定义选项卡配置组件。

要将您的组件包含在 Lightning Experience 应用程序中,并使其可供组织中的桌面和移动用户使用,请执行以下步骤。

  1. 为组件创建自定义选项卡。
    1. 在“设置”中,输入“快速查找”框,然后选择“选项卡”。Tabs
    2. 单击 Lightning 组件选项卡相关列表中的新建
    3. 选择要提供给用户的 Lightning 组件。
    4. 输入要在选项卡上显示的标签。
    5. 选择选项卡样式,然后单击下一步
    6. 当系统提示将选项卡添加到配置文件时,接受默认值,然后单击保存。您的 Lightning 组件现在可从桌面应用程序启动器的“所有项目”部分和 Salesforce 移动应用程序的“所有项目”导航菜单项获得。
  2. 将您的 Lightning 组件添加到 Lightning 应用程序的导航中。
    1. 在“设置”中,输入“快速查找”框,然后选择“应用程序管理器”。Apps
    2. 编辑现有应用程序或创建应用程序。
    3. 在“导航项目”屏幕上,从“可用项目”列表中选择您的 Lightning 组件选项卡,并将其移动到“所选项目”列表。
    4. 保存应用。
  3. 检查输出。
    1. 在桌面上的 Lightning Experience 或 Salesforce 移动应用程序中导航到应用程序启动器。
    2. 搜索自定义应用名称,然后单击它。
    3. 查看您添加的组件。

针对不同的外形规格配置组件

将组件配置为在以桌面格式 ()、手机格式 () 或两者呈现页面时显示在 Lightning 应用程序页面上。LargeSmall

在组件配置文件的部分中,使用标记集来声明组件支持页面类型的外形规格。<targetConfigs><supportedFormFactors>

如果未定义,则组件支持页面类型支持的外形规格。但是,我们建议为每个页面类型进行定义。<supportedFormFactors><supportedFormFactors>

应用和记录页面支持 和 外形规格。主页仅支持外形规格。LargeSmallLarge

应用和记录页面上的组件可以在手机和桌面上呈现,因为这些页面同时支持手机和桌面。主页上的组件只能在桌面上呈现,因为主页仅支持桌面。

此示例组件在三种页面类型上受支持:应用、记录和主页。在应用页面上,它配置为仅在具有外形规格的设备上呈现。当用户在具有外形规格的设备上查看应用页面时,该组件不会呈现。SmallLarge

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>42.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>Best Component Ever</masterLabel>
    <description>This is a demo component.</description>
    <targets>
        <target>lightning__RecordPage</target>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__AppPage">
            <property name="prop2" type="Boolean" />
            <supportedFormFactors>
                <supportedFormFactor type="Small" />
            </supportedFormFactors>
        </targetConfig>
        <targetConfig targets="lightning__RecordPage">
            <property name="prop1" type="String" />
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
            </supportedFormFactors>
        </targetConfig>
        <targetConfig targets="lightning__HomePage">
            <property name="prop3" type="Integer" />
            <supportedFormFactors>
                <supportedFormFactor type="Large" />
            </supportedFormFactors>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

注意

在 Lightning 页面上使用组件后,您只能增加该组件支持的外形规格,而不能减小它们。

使组件了解其上下文

组件可以知道其记录上下文、对象上下文及其在 Lightning 应用程序生成器中的区域宽度。

使组件了解其记录上下文

在某些用例中,让组件了解其记录上下文会很有帮助。例如,您希望提供记录上下文,以便组件可以在查看的记录页面上返回和显示子记录信息。要使组件了解其对象上下文,请使用 Lightning 记录页面上的属性。然后,该页将该属性设置为当前记录的 ID。recordId

提示

lwc-recipes 存储库有一个 wireGetRecordDynamicContact 组件,该组件返回正在查看的联系人记录的一些数据。

在 Lightning Experience 中访问记录上下文

在组件的 JavaScript 类中,使用修饰器创建公共属性。@apirecordId

// testClass.js
import { LightningElement, api } from "lwc";
export default class TestClass extends LightningElement {
  @api recordId;
}

在 Lightning Experience 或移动应用程序的记录上下文中调用组件时,recordId 设置为记录的 18 个字符的 ID,例如:。001xx000003DGSWAA4

重要

仅当您在显式记录上下文中放置或调用组件时,才会自动设置 。在所有其他情况下,不会设置 ,并且组件不能依赖于它。在这种情况下,您可以设置自己。例如,用于快速操作的组件在记录页面上使用时,可以显式设置是否需要访问记录 ID。recordIdrecordIdrecordIdrecordId

在 Experience Builder 站点中访问记录上下文

Experience Builder 站点不会自动绑定到组件的模板。recordId

包含修饰器以在组件上创建公共属性后,在组件的文件中添加表达式。参数中指定的所有页面类型都可以访问记录 ID。@apirecordIdrecordId*.js-meta.xmltargets

<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>

在Experience Builder站点的记录上下文中调用组件时,表达式将设置为记录的18个字符的ID。"{!recordId}"

使组件了解其对象上下文

在某些用例中,使组件了解其对象上下文会很有帮助。例如,您希望提供对象上下文,以便组件可以根据页面上正在查看的对象返回一些信息。要使组件了解其对象上下文,请使用 Lightning 记录页面上的属性。然后,页面将该属性设置为当前对象的 API 名称。objectApiName

提示

lwc-recipes 存储库有一个 wireGetObjectInfo 组件,该组件返回所选对象的对象信息。

在 Lightning Experience 中访问对象上下文

在组件的 JavaScript 类中,使用修饰器创建公共属性。@apiobjectApiName

// testClass.js
import { LightningElement, api } from "lwc";
export default class TestClass extends LightningElement {
  @api objectApiName;
}

在 Lightning Experience 或移动应用程序的记录上下文中调用组件时,将设置为与正在查看的记录关联的对象的 API 名称,例如:。objectApiNameWarehouse__c

重要

仅当您在显式记录上下文中放置或调用组件时,才会设置 。在所有其他情况下,未设置 ,并且组件不应依赖于它。objectApiNameobjectApiName

在Experience Builder Sites中访问对象上下文

Experience Builder 站点不会自动绑定到组件的模板。objectApiName

包含修饰器以在组件上创建公共属性后,在组件的文件中添加表达式。参数中指定的所有页面类型都可以访问对象名称。@apiobjectApiNameobjectApiName*.js-meta.xmltargets

注意

此方法仅适用于 在路由中 的组件。{!objectApiName}

<targetConfigs>
  <targetConfig targets="lightningCommunity__Default">
    <property
      name="objectApiName"
      type="String"
      label="Object Name"
      description="Automatically bind the page's object name to the component variable"
      default="{!objectApiName}"
    />
  </targetConfig>
</targetConfigs>

在Experience Builder站点的对象上下文中调用组件时,表达式将设置为对象的18个字符的ID。objectApiName

使组件具有宽度感知能力

当您在 Lightning 应用程序构建器中将组件添加到页面上的区域时,请使用将区域的宽度传递给组件。然后,通过一些战略性的 CSS,你可以告诉组件在运行时以不同的方式在不同的区域中呈现。@api flexipageRegionWidth

例如,列表视图组件在大区域中的呈现方式与在小区域中的呈现方式不同,因为它是宽度感知组件。

在组件的 JavaScript 类中,使用修饰器创建公共属性。此属性接收组件在页面上所在的区域的宽度值。@apiflexipageRegionWidth

// testClass.js
import { LightningElement, api } from "lwc";

export default class TestClass extends LightningElement {
  @api flexipageRegionWidth;
}

使用 HTML 模板中的属性。当值更改时,组件将重新呈现。flexipageRegionWidthflexipageRegionWidth

<!-- testClass.html -->
<template>
  <div class={flexipageRegionWidth}>...</div>
</template>

使用 CSS 定义组件在以不同区域宽度呈现时的行为。有效的 CSS 类值为 、 和 。此示例 CSS 代码段告诉组件在大型区域中时以红色背景呈现。当它位于一个小区域时,它以蓝色背景呈现。SMALLMEDIUMLARGE

/* testClass.css */

div.LARGE {
  background: red;
  ...;
}
div.SMALL {
  background: blue;
  ...;
}