Skip to main content

创建 Lightning Web 组件

学习目标

完成本单元后,您将能够:

  • 描述每个组件文件的内容。
  • 为 Lightning web 组件创建 JavaScript 方法。
  • 在组件 JavaScript 中使用生命周期钩子。

使用时间

假设您想要构建一个独立于 Salesforce 中特定对象的数据显示元素。ebikes 示例报表中的 productCard 组件就是一个很好的例子。让我们研究一下该卡片组件,并从头开始构建我们自己的版本,这样您便能够了解它是如何演变成一个名副其实的 Lightning web 组件的。当您构建组件的各个部分并探索更多示例时,您很快便能掌握相关基础知识。

升级到组织

在本单元中,我们使用带 Salesforce 扩展包的 Visual Studio Code 开发了一个 Lightning web 组件。

所需内容

如第一单元所述,您需要对 Salesforce DX 有所了解才能继续操作。若要完成本单元,您需要:

  • 带有 Salesforce 扩展包的 Visual Studio Code (VS Code)
  • Salesforce CLI

完成快速入门:Lightning Web 组件项目,以达成这些要求。

了解 HTML 文件

Lightning web 组件的 HTML 文件均包含 template(模板)标签。该 template(模板)标签包含定义组件结构的 HTML。让我们看一下 ebikes 存储库中简化版 productCard 组件的 HTML。

按照步骤将这些示例粘贴到 VS Code 中。

  1. 在 VS Code 命令面板中选择 SFDX: Create Project(SFDX:创建项目)来创建新项目。接受标准模板,并给项目起名为 bikeCard
  2. force-app/main/default 下,右击 lwc 文件夹,选择 SFDX: Create Lightning Web Component(SFDX:创建 Lightning Web 组件)
  3. 输入 app 作为新组件的名称。
  4. 按下 Enter,然后再次按 Enter 以接受默认 force-app/main/default/lwc
  5. 将以下代码粘贴到 app.html 中(替换文件中现有的 HTML)。
    <template>
      <div>
        <div>Name: {name}</div>
        <div>Description: {description}</div>
        <div>Category: {category}</div>
        <div>Material: {material}</div>
        <div>Price: {price}</div>
        <div><img src={pictureUrl} alt={name}/></div>
      </div>
    </template>
    花括号 {} 中的识别码被绑定到相应 JavaScript 类中的同名字段。
  6. 将以下代码粘贴到 app.js 中。
    import { LightningElement } from 'lwc';
    export default class App extends LightningElement {
      name = 'Electra X4';
      description = 'A sweet bike built for comfort.';
      category = 'Mountain';
      material = 'Steel';
      price = '$2,700';
      pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
    }
  7. 保存文件。

现在让我们来看一个真实的例子。假设您想要显示数据,但加载需要一些时间,您不希望让用户知道发生了什么。您可以在模板中使用 lwc:iflwc:else 条件指令来确定要渲染哪些视觉元素。

  1. 将以下代码粘贴到 app.html 中。在 HTML 文件中 ready 的值为 true 之前,“display”div 标签中的内容不会出现。
    <template>
      <template lwc:if={ready}>
        <div id="display">
          <div>Name: {name}</div>
          <div>Description: {description}</div>
          <div>Category: {category}</div>
          <div>Material: {material}</div>
          <div>Price: {price}</div>
          <div><img src={pictureUrl} alt={name}/></div>
        </div>
      </template>
      <template lwc:else>
        <div id="waiting">Loading…</div>
      </template>
    </template>
  2. 将以下代码粘贴到 app.js 中。这能保存我们的数据值并设置 3 秒计时器。3 秒后,应显示内容。(当然,这样做只是为了进行测试。)
    import { LightningElement } from 'lwc';
    export default class App extends LightningElement {
      name = 'Electra X4';
      description = 'A sweet bike built for comfort.';
      category = 'Mountain';
      material = 'Steel';
      price = '$2,700';
      pictureUrl = 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg';
      ready = false;
      connectedCallback() {
        setTimeout(() => {
          this.ready = true;
        }, 3000);
      }
    }
  3. 保存文件。

基本 Lightning Web 组件

现在,您不想从头开始构建所有组件。所以让我们来探讨一下如何使用基本 Lightning web 组件。当然,还有很多组件,包括字段类型、显示控制器、导航项等。所有这些都在组件引用中列出。

让我们将 Bike 的细节突出出来。在 app.html 文件中,用 lightning-badge 组件替换上一个例子中 material 和 category 的 div 标签。HTML 如下所示。

<template>
  <template lwc:if={ready}>
    <div id="display">
      <div>Name: {name}</div>
      <div>Description: {description}</div>
      <lightning-badge label={material}></lightning-badge>
      <lightning-badge label={category}></lightning-badge>
      <div>Price: {price}</div>
      <div><img src={pictureUrl} alt={name}/></div>
    </div>
  </template>
  <template lwc:else>
    <div id="waiting">Loading…</div>
  </template>
</template>

保存文件。

SteelMountain 这两个词便会作为徽章出现。就是这么简单。

组件构建结构

一个组件只需要一个具有相同名称的文件夹和文件。它们会根据名字和位置自动关联。

一个文件夹中的组件文件

所有 Lightning web 组件都有一个命名空间,用连字符与文件夹名分开。例如,在默认命名空间 c 中,文件夹名为 app 的 Lightning web 组件的标记为 <c-app>

但是,Salesforce 平台不允许在组件的文件夹名或文件名中使用连字符。如果组件的名字有多个单词,比如 mycomponent,该怎么办?您不能将文件夹和文件命名为 my-component,这里,我们提供一个更方便的解决方案。

采用驼峰式大小写命名法,将组件命名为 myComponent。采用驼峰式大小写命名法的组件文件夹名在标记中采用串式命名法。在标记中,若要引用文件夹名为 myComponent 的组件,请使用 <c-my-component>

例如 LWC 示例报表的 viewSource 文件夹包含 viewSource 组件的文件。当 hello 组件引用 HTML 中的 viewSource 组件时,它使用 c-view-source

很好!我们来看一下 JavaScript。

使用 JavaScript

这是让您领会奥妙的时刻。正如您到目前为止所看到的,JavaScript 方法定义了如何处理输入、数据、事件、状态变化等,以让组件能正常发挥作用。

Lightning web 组件的 JavaScript 文件必须包含以下代码,其中 MyComponent 是您为组件类分配的名称。

import { LightningElement } from 'lwc';
export default class MyComponent extends LightningElement {
}

export 语句定义了一个可扩展 LightningElement 类的类。作为最佳实践,类的名称通常与 JavaScript 类的文件名相匹配,但这不是强制要求。

LWC 模块

Lightning Web 组件(ECMAScript 6 中引入了内置模块)使用模块来捆绑核心功能,并使其能在您的组件文件中被 JavaScript 访问。Lightning web 组件的核心模块是 lwc

import(导入)语句开始模块,并指定组件要使用的模块功能。

import(导入)语句表示 JavaScript 使用了 lwc 模块中的 LightningElement 功能。

// import module elements
import { LightningElement} from 'lwc';
// declare class to expose the component
export default class App extends LightningElement {
  ready = false;
  // use lifecycle hook
  connectedCallback() {
    setTimeout(() => {
      this.ready = true;
    }, 3000);
  }
}
  • LightningElement 是 Lightning web 组件的基类,使我们能够使用 connectedCallback()
  • connectedCallback() 方法是生命周期钩子之一。在下一节中,您将了解有关生命周期钩子的更多信息。现在,当在文档对象模型 (DOM) 中插入组件时会触发该方法。在这种情况下,计时器会启动。

生命周期钩子

Lightning Web 组件提供了方法,使您的代码能够“钩住”组件生命周期中的关键事件。这些事件包括当一个组件被:

  • 创建
  • 添加至 DOM
  • 在浏览器中渲染
  • 遇到错误
  • 从 DOM 中删除

使用回调方法响应这些生命周期事件中的任一个。例如,当将组件插入 DOM 中时,会调用 connectedCallback()。当将组件从 DOM 中删除时,会调用 disconnectedCallback()

在我们用于测试条件渲染的 JavaScript 文件中,我们使用 connectedCallback() 方法,当将组件插入 DOM 中时会自动执行代码。代码等待 3 秒钟,然后将 ready 设置为 true

import { LightningElement } from 'lwc';
export default class App extends LightningElement {
  ready = false;
  connectedCallback() {
    setTimeout(() => {
      this.ready = true;
    }, 3000);
  }
}
备注

当您在诸如 VS Code 之类的编辑器中使用这个例子时,您可能会看到 setTimeout() 函数的 lint 警告“受限制的异步操作”。这个警告表明您正在使用一个经常被误用的异步操作;它根据时间延迟行为,而非等待事件。在这种情况下,setTimeout() 适用于演示任意的时间延迟,并且这个警告不应该阻止您使用它。

另外,请注意我们使用了关键字 this。如果您写过 JavaScript,就应该很熟悉关键字的用法,就像在其他环境中使用它一样。JavaScript 中的 this 关键字指的是当前上下文的顶层。在此处,上下文就是这个类。connectedCallback() 方法为顶层的 ready 变量赋值。这是揭示 Lightning Web 组件如何帮助您将 JavaScript 功能引入开发的一个很好的示例。您可以在“资源”部分找到有关 this 具体信息的链接。

装饰器

在 JavaScript 中,装饰器经常用于修改一个属性或函数的行为。

若要使用装饰器,需要从 lwc 模块中导入它,并将其放在属性或函数之前。

import { LightningElement, api } from 'lwc';
export default class MyComponent extends LightningElement{
  @api message;
}

您可以导入多个装饰器,但是一个属性或函数只能有一个装饰器。例如,一个属性不能同时有 @api@wire 装饰器。

Lightning Web 组件装饰器的例子包括:

  • @api:将字段标记为公共字段。公共属性定义组件的 API。在其 HTML 标记中使用该组件的 owner 组件可以访问该组件的公共属性。所有公共属性都是响应式的,这意味着框架会观察属性的更改。当属性值发生变化时,框架会做出反应并重新渲染该组件。
备注

字段和属性几乎是可互换的术语。组件作者在 JavaScript 类中声明字段。类的实例具有属性。对于组件使用者来说,字段就是属性。在 Lightning web 组件中,只有组件作者用 @api 装饰的字段才能作为对象属性公开提供给使用者。

  • @track:告诉框架观察对象属性或数组元素发生的变化。如果发生变化,框架会重新渲染组件。所有字段都是反应式的。如果字段的值发生变化,并且该字段用于模板中,或者用于模板中所用属性的 getter 中,则框架会重新渲染该组件。您无需用 @track 来装饰字段。仅当字段包含对象或数组,并且您希望框架观察对象属性或数组元素发生的变化时,才使用 @track。如果您要更改整个属性的值,则无需使用 @track
备注

在 Spring '20 之前,您必须用 @track 将字段(也称为私有属性)标记为反应字段。您不需要再那样做了。使用 @track 仅告诉框架观察对象属性或数组元素发生的变化。一些旧例子可能仍然在不需要的地方使用 @track,但这没关系,因为使用装饰器不会更改功能或破坏代码。

  • @wire:为您提供了一种从 Salesforce 组织获取和绑定数据的简单方法。

下面是使用 @api 装饰器在一个组件 (app) 中渲染另一个组件 (bike) 的值的例子。文件结构如下所示:

app 文件结构示例。

app 组件使用以下 HTML。

<!-- app.html -->
<template>
  <div>
    <c-bike bike={bike}></c-bike>
  </div>
</template>

app 组件使用以下 JavaScript。

// app.js
import { LightningElement } from 'lwc';
export default class App extends LightningElement {
  bike = {
    name: 'Electra X4',
    picture: 'https://s3-us-west-1.amazonaws.com/sfdc-demo/ebikes/electrax4.jpg'
  };
}

bike 组件使用以下 HTML。

<!-- bike.html -->
<template>
  <img src={bike.picture} alt="bike picture" />
  <p>{bike.name}</p>
</template>

bike 组件使用以下 JavaScript。

// bike.js
import { LightningElement, api } from 'lwc';
export default class Bike extends LightningElement {
  @api bike;
}

学习进展很快,您已经能够使用 VS Code 中的一些代码。在下一单元中,我们将部署一些代码,并详细讨论组件的生存环境。

资源

在 Salesforce 帮助中分享 Trailhead 反馈

我们很想听听您使用 Trailhead 的经验——您现在可以随时从 Salesforce 帮助网站访问新的反馈表单。

了解更多 继续分享反馈