创建 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 中。
- 在 VS Code 命令面板中选择 SFDX: Create Project(SFDX:创建项目)来创建新项目。接受标准模板,并给项目起名为
bikeCard
。
- 在 force-app/main/default 下,右击 lwc 文件夹,选择 SFDX: Create Lightning Web Component(SFDX:创建 Lightning Web 组件)。
- 输入
app
作为新组件的名称。
- 按下 Enter,然后再次按 Enter 以接受默认
force-app/main/default/lwc
。
- 将以下代码粘贴到 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 类中的同名字段。
- 将以下代码粘贴到 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'; }
- 保存文件。
现在让我们来看一个真实的例子。假设您想要显示数据,但加载需要一些时间,您不希望让用户知道发生了什么。您可以在模板中使用 lwc:if
和 lwc:else
条件指令来确定要渲染哪些视觉元素。
- 将以下代码粘贴到 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>
- 将以下代码粘贴到 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); } }
- 保存文件。
基本 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>
保存文件。
Steel 和 Mountain 这两个词便会作为徽章出现。就是这么简单。
组件构建结构
一个组件只需要一个具有相同名称的文件夹和文件。它们会根据名字和位置自动关联。
所有 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); } }
另外,请注意我们使用了关键字 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 组件可以访问该组件的公共属性。所有公共属性都是响应式的,这意味着框架会观察属性的更改。当属性值发生变化时,框架会做出反应并重新渲染该组件。
-
@track:告诉框架观察对象属性或数组元素发生的变化。如果发生变化,框架会重新渲染组件。所有字段都是反应式的。如果字段的值发生变化,并且该字段用于模板中,或者用于模板中所用属性的 getter 中,则框架会重新渲染该组件。您无需用
@track
来装饰字段。仅当字段包含对象或数组,并且您希望框架观察对象属性或数组元素发生的变化时,才使用@track
。如果您要更改整个属性的值,则无需使用@track
。
-
@wire:为您提供了一种从 Salesforce 组织获取和绑定数据的简单方法。
下面是使用 @api
装饰器在一个组件 (app) 中渲染另一个组件 (bike) 的值的例子。文件结构如下所示:
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 中的一些代码。在下一单元中,我们将部署一些代码,并详细讨论组件的生存环境。
资源
- Lightning Web 组件开发人员指南:反应
- Lightning Web 组件开发人员指南:引用(包括 HTML 模板指令、装饰器等)
- MDN Web 文档:this