Lightning Web 组件是具有自己的 API 的可重用自定义 HTML 元素。
请查看这些部分,了解有关创建自己的 Lightning Web 组件的更多信息。
- 定义组件
- HTML 模板
- CSS的
- 组成
- 字段、属性和特性
- Javascript的
- 访问 Salesforce 资源
- 组件可访问性
- 生命周期钩子
定义组件
呈现 UI 的 Lightning Web 组件必须包含 HTML 文件、JavaScript 文件和元数据配置文件。这些文件必须使用相同的名称,以便框架可以自动连接它们。服务组件(库)必须包含 JavaScript 文件和元数据配置文件。
另见
- Lightning Web 组件视频库:LWC 剖析
HTML 模板
Lightning Web 组件的强大之处在于模板系统,它使用虚拟 DOM 来智能高效地渲染组件。最好的做法是让 LWC 操作 DOM,而不是编写 JavaScript 来执行此操作。
在 HTML 模板中使用根标记。您还可以使用嵌套标记来处理指令。<template><template>
使用 HTML 模板
使用标准 HTML 和一些 Lightning Web 组件特有的指令编写模板。
当组件呈现时,标记将替换为组件的名称 。<template>
<namespace-component-name>
<!-- myComponent.html -->
<template>
<div class="slds-var-m-around_medium">Hello World</div>
</template>
例如,在浏览器控制台中,带有模板的组件呈现为 ,其中 是默认命名空间。myComponent.html
<c-my-component>
c
<c-my-component>
<div class="slds-var-m-around_medium">Hello, World!</div>
</c-my-component>
HTML 模板还将数据呈现给 DOM。 使用简单的语法以声明方式将组件的模板绑定到组件的 JavaScript 类中的数据。
嵌套模板
模板可以包含带有指令的嵌套标记。<template>
指令是特殊的 HTML 属性,如 和 ,它赋予您在标记中操作 DOM 的更多权力。lwc:if
for:each
嵌套标记必须包含以下指令之一:、、或 。<template>
for:each
iterator:iteratorName
lwc:if
lwc:else
lwc:elseif
if:true|false
注意
嵌套标记不能与其他指令或 HTML 属性一起使用。无效的模板用法将被忽略 – 模板及其子级不会在 DOM 中呈现,并且在加载组件时会返回警告。<template>
例如,不要在嵌套标签上使用该属性,而是在 or 标签上使用该属性。class
<template>
class
<div>
<span>
提示
如果您使用 VS Code,我们建议您安装 Salesforce 扩展包。此扩展会在您键入时标记格式错误或不正确的代码,这在使用模板指令时很有帮助。
有关根标记或嵌套标记支持哪些指令的详细信息,请参阅 HTML 模板指令。<template>
模板中的数据绑定
将组件模板中的属性绑定到组件的 JavaScript 类中的属性。
在模板中,用不带空格的大括号将属性括起来:.若要计算属性的值,请在 JavaScript 类 property
中使用 JavaScript getter。在模板中,属性
可以是 JavaScript 标识符(例如,),也可以是从对象 () 访问属性的点表示法。LWC 不允许使用像 这样的计算表达式。{property}
get
(){}
person
person.firstName
person[2].name['John']
模板中使用的属性应包含基元值,但在 for:each
或迭代器
指令中使用时除外。
示例:将组件模板属性绑定到 JavaScript 属性
若要在代码编辑器中继续操作,请打开 github.com/trailheadapps/lwc-recipes 存储库中的 、 和组件。您也可以将代码复制到 webcomponents.dev/create/lwc。hellohelloBindinghelloExpressions
下面是数据绑定的最简单示例。模板中的属性绑定到 JavaScript 类中的属性。greeting
greeting
<!-- hello.html -->
<template> Hello, {greeting}! </template>
// hello.js
import { LightningElement } from "lwc";
export default class Hello extends LightningElement {
greeting = "World";
}
中的属性必须是有效的 JavaScript 标识符或成员表达式。例如,和 都有效。不要在属性周围添加空格,例如,不是有效的 HTML。{ }
{data}
{data.name}
{ data }
此组件没有硬编码字符串,而是具有一个输入字段,该字段要求提供要问候的名称。
该字段使用该属性来侦听其值的更改。当值更改时,将执行 JavaScript 文件中的函数。请注意,要将函数绑定到模板,我们使用相同的语法,lightning-input
onchange
handleChange
handleChange
{handleChange}
<!-- helloBinding.html -->
<template>
<p>Hello, {greeting}!</p>
<lightning-input label="Name" value={greeting} onchange={handleChange}></lightning-input>
</template>
我们在另一个主题中深入讨论事件处理,但请注意,在 JavaScript 类中传递了一个对象。该对象包含有关更改事件的信息。该组件使用该对象来获取用户在输入字段中输入的值。handleChangeeventeventevent
// helloBinding.js
import { LightningElement } from "lwc";
export default class HelloBinding extends LightningElement {
greeting = "World";
handleChange(event) {
this.greeting = event.target.value;
}
}
这些代码大部分是标准的 HTML 和 JavaScript。
注意
当组件重新呈现时,将重新计算模板中使用的表达式。
使用 getter 代替表达式
若要计算属性的值,请使用 JavaScript getter。例如,若要将名称转换为所有大写字母,请在 JavaScript 类中使用 getter 函数,而不是模板中的表达式。
getter 比表达式强大得多,因为它们是 JavaScript 函数。Getter 还支持单元测试,从而减少错误并增加乐趣。
定义一个 getter 来计算 JavaScript 类中的值。
get propertyName() { ... }
从模板访问 getter。
{
propertyName;
}
在此示例中,用户输入其名字和姓氏。JavaScript getter 计算一个新值,模板呈现它:DEANNA LI。uppercasedFullName
模板中的属性绑定到 JavaScript 类中的 getter。uppercasedFullName
get uppercasedFullName()
<!-- helloExpressions.html -->
<template>
<div class="slds-m-around_medium">
<lightning-input
name="firstName"
label="First Name"
onchange={handleChange}
></lightning-input>
<lightning-input name="lastName" label="Last Name" onchange={handleChange}></lightning-input>
<p class="slds-m-top_medium">Uppercased Full Name: {uppercasedFullName}</p>
</div>
</template>
该函数将 和 属性设置为用户输入的值。getter 将名称组合并大写。handleChange
firstName
lastName
uppercasedFullName()
// helloExpressions.js
import { LightningElement } from "lwc";
export default class HelloExpressions extends LightningElement {
firstName = "";
lastName = "";
handleChange(event) {
const field = event.target.name;
if (field === "firstName") {
this.firstName = event.target.value;
} else if (field === "lastName") {
this.lastName = event.target.value;
}
}
get uppercasedFullName() {
return `${this.firstName} ${this.lastName}`.toUpperCase();
}
}
提示
所有字段都是反应式的。如果字段在模板中使用,或间接用于模板中使用的属性的 getter 中,则当属性的值更改时,组件将重新呈现。在此示例中,when 和 change 会重新呈现模板,因为它们在 getter 中使用,并且该属性在模板中使用。请参阅字段、对象和数组的反应性。firstName lastName uppercasedFullName
有条件地呈现 DOM 元素
若要有条件地呈现 HTML,请将 and 指令添加到包含条件内容的嵌套标记中。lwc:if|elseif={property}
lwc:else
<template>
提示
指令是特殊的 HTML 属性。Lightning Web 组件编程模型具有一些自定义指令,允许您使用标记来操作 DOM。
这些指令绑定到模板,根据数据是真实值还是虚假值来删除和插入 DOM 元素。lwc:if|elseif{property}
注意
不再建议使用旧指令和指令,因为我们打算在将来弃用和删除这些指令。我们建议您将其用条件指令替换为条件指令,以使您的代码面向未来。if:true
if:false
lwc:if|elseif|else
此示例有两个属性和 。property1
property2
<template>
<template lwc:if={property1}> Statement1 </template>
<template lwc:elseif={property2}> Statement2 </template>
<template lwc:else> Statement3 </template>
</template>
这三个语句中只有一个呈现:
Statement1
如果为 true,则呈现。property1
Statement2
如果为 false,则呈现 true。property1
property2
Statement3
呈现 if 和 are false。property1
property2
尽管该示例使用所有三个指令,并且是可选的。lwc:elseif
lwc:else
让我们看另一个例子。此模板包含一个标记为“显示详细信息”的复选框。当用户选中或取消选中该复选框时,该函数将设置属性的值。如果属性为 ,则该指令将呈现嵌套模板,该模板显示 These are the details!。handleChange
areDetailsVisible
areDetailsVisible
true
lwc:if
<!-- helloConditionalRendering.html -->
<template>
<lightning-card title="HelloConditionalRendering" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<lightning-input
type="checkbox"
label="Show details"
onchange={handleChange}
></lightning-input>
<template lwc:if={areDetailsVisible}>
<div class="slds-m-vertical_medium">These are the details!</div>
</template>
</div>
</lightning-card>
</template>
请注意,JavaScript 不会操作 DOM,它只是更改属性的值。
// helloConditionalRendering.js
import { LightningElement } from "lwc";
export default class HelloConditionalRendering extends LightningElement {
areDetailsVisible = false;
handleChange(event) {
this.areDetailsVisible = event.target.checked;
}
}


注意
若要在标记中切换布尔属性的值,请将该值默认为 。请参见布尔属性。false
提示
此示例代码是 github.com/trailheadapps/lwc-recipes 存储库中的组件。helloConditionalRendering
渲染列表
若要呈现项列表,请使用 directive 或 the directive 循环访问数组。将该指令添加到包含要重复的 HTML 元素的嵌套标记中。for:each
iterator
<template>
该指令具有 和 属性,可用于将特殊行为应用于数组中的第一个和最后一个项目。iterator
first
last
无论使用哪个指令,都必须使用指令为每个项目分配唯一的 ID。当列表更改时,框架使用 仅重新呈现已更改的项。模板中的 用于性能优化,在运行时不会反映在 DOM 中。key
key
key
提示
若要在代码编辑器中继续操作,请打开 github.com/trailheadapps/lwc-recipes 存储库中的 和组件。还可以将代码复制到组件 IDE。helloForEachhelloIterator
适合:每个
使用该指令时,use 用于访问当前项目。此示例不使用它,但要访问当前项的索引,请使用 .for:each
for:item="currentItem"
for:index="index"
若要将键分配给嵌套模板中的第一个元素,请使用该指令。key={uniqueId}
此示例循环访问一个名为 的数组,该数组在组件的 JavaScript 类中定义。contacts
<!-- helloForEach.html -->
<template>
<lightning-card title="HelloForEach" icon-name="custom:custom14">
<ul class="slds-m-around_medium">
<template for:each={contacts} for:item="contact">
<li key={contact.Id}>{contact.Name}, {contact.Title}</li>
</template>
</ul>
</lightning-card>
</template>
// helloForEach.js
import { LightningElement } from "lwc";
export default class HelloForEach extends LightningElement {
contacts = [
{
Id: 1,
Name: "Amy Taylor",
Title: "VP of Engineering",
},
{
Id: 2,
Name: "Michael Jones",
Title: "VP of Sales",
},
{
Id: 3,
Name: "Jennifer Wu",
Title: "CEO",
},
];
}

重要
列表中的每个项目都必须具有 .当列表更改时,框架使用 来标识每个项目,以便它只能重新呈现已更改的项目。必须是字符串或数字,不能是对象。不能用作 的值。为传入数据集分配唯一键。若要将新项添加到数据集,请使用私有属性来跟踪和生成键。key
key
key
index
key
迭 代
若要将特殊行为应用于列表中的第一项或最后一项,请使用指令 。在标记上使用指令。iterator
iterator:iteratorName={array}
iterator
template
使用 iteratorName
访问以下属性:
value
– 列表中项目的值。使用此属性可访问数组的属性。例如。{iteratorName}.value.{propertyName}
index
– 列表中项目的索引。first
– 一个布尔值,指示此项目是否为列表中的第一项。last
– 一个布尔值,指示此项目是否为列表中的最后一项。
此示例代码使用与上一个示例相同的数组。若要将特殊呈现应用于列表中的第一项和最后一项,代码将 and 属性与指令一起使用。first
last
lwc:if
如果项目位于列表中的第一个,则标记将使用 CSS 类中定义的样式进行呈现。如果项目在列表中排在最后,则标记将使用 CSS 类中定义的样式进行呈现。<div>
list-first
<div>
list-last
<template>
<lightning-card title="HelloIterator" icon-name="custom:custom14">
<ul class="slds-m-around_medium">
<template iterator:it={contacts}>
<li key={it.value.Id}>
<div lwc:if={it.first} class="list-first"></div>
{it.value.Name}, {it.value.Title}
<div lwc:if={it.last} class="list-last"></div>
</li>
</template>
</ul>
</lightning-card>
</template>
.list-first {
border-top: 1px solid black;
padding-top: 5px;
}
.list-last {
border-bottom: 1px solid black;
padding-bottom: 5px;
}

例
lwc-recipes 存储库中的组件使用基本组件来显示选择列表值列表。wireGetPicklistValues lightning-input
渲染多个模板
您可能希望呈现具有多种外观的组件,但不希望将 HTML 混合在一个文件中。例如,组件的一个版本是纯文本,另一个版本显示图像和额外的文本。在这种情况下,您可以导入多个 HTML 模板并编写有条件地呈现这些模板的业务逻辑。此模式类似于某些 JavaScript 框架中使用的代码拆分。
注意
尽管一个组件可以呈现多个模板,但我们建议改用指令有条件地呈现嵌套模板。lwc:if|elseif|else
在组件包中创建多个 HTML 文件。将它们全部导入,并在方法中添加条件,以根据组件的状态返回正确的模板。该方法返回的值必须是模板引用,这是从 HTML 文件导入的默认导出。render()
render()
在此示例中,模板引用是 和 。templateOne
templateTwo
// miscMultipleTemplates.js
import { LightningElement } from "lwc";
import templateOne from "./templateOne.html";
import templateTwo from "./templateTwo.html";
export default class MiscMultipleTemplates extends LightningElement {
showTemplateOne = true;
render() {
return this.showTemplateOne ? templateOne : templateTwo;
}
switchTemplate() {
this.showTemplateOne = !this.showTemplateOne;
}
}
<!-- templateOne.html -->
<template>
<lightning-card title="Template One">
<div>This is template one.</div>
<p class="margin-vertical-small">
<lightning-button label="Switch Templates" onclick={switchTemplate}> </lightning-button>
</p>
</lightning-card>
</template>
<!-- templateTwo.html -->
<template>
<lightning-card title="Template Two">
<div>This is template two.</div>
<p class="margin-vertical-small">
<lightning-button label="Switch Templates" onclick={switchTemplate}> </lightning-button>
</p>
</lightning-card>
</template>
若要从额外模板引用 CSS,CSS 文件名必须与额外模板的文件名匹配。例如,只能从 引用 CSS。它不能从 或 引用 CSS。templateTwo.html
templateTwo.css
miscMultipleTemplates.css
templateOne.css
MiscMultipleTemplates
├──miscMultipleTemplates.js
├──miscMultipleTemplates.js-meta.xml
├──templateOne.html
├──templateOne.css
├──templateTwo.html
└──templateTwo.css
如果包含具有匹配名称的模板,则默认方法将返回该模板,除非包含上一示例中讨论的替代。miscMultipleTemplates.html
render()
提示
查看 lwc-recipes 存储库中的组件。miscMultipleTemplates