组件

您可以在另一个组件的主体中添加组件。组合使您能够从更简单的构建块组件构建复杂的组件。

注意

允许继承,但不建议这样做,因为组合通常更有效。若要在组件之间共享逻辑,请使用仅包含逻辑的模块。请参阅其他 JavaScript 文件。如果您选择使用继承,请注意,它不适用于 Lightning Locker 下的命名空间。您必须启用 LWS 才能跨命名空间使用继承。不能在任一安全体系结构中扩展命名空间。lightning

Compose 组件

使用一组较小的组件组合应用和组件非常有用,以使代码更易于重用和维护。命名空间包含许多基本组件,例如 ,您可以使用这些组件来构建组件。lightninglightning-button

让我们看一个由组件组成的简单应用程序。标记是人为的,因为我们想说明所有者容器的概念。在实际应用中,实例的数量是可变的,并在循环中动态填充。c-todo-itemfor:each

<!-- todoApp.html -->
<template>
  <c-todo-wrapper>
    <c-todo-item item-name="Milk"></c-todo-item>
    <c-todo-item item-name="Bread"></c-todo-item>
  </c-todo-wrapper>
  <template></template
></template>

所有者

所有者是拥有模板的组件。在此示例中,所有者是组件。所有者控制其包含的所有组合组件。所有者可以:c-todo-app

  • 在组合组件上设置公共属性
  • 在组合组件上调用方法
  • 侦听组合组件触发的任何事件

容器

容器包含其他组件,但其本身包含在所有者组件中。在此示例中,是一个容器。容器不如所有者强大。容器可以:c-todo-wrapper

  • 读取但不能更改包含组件中的公共属性
  • 在组合组件上调用方法
  • 侦听它所包含的组件冒泡的一些(但不一定是全部)事件。

父母和孩子

当一个组件包含另一个组件时,另一个组件又可以包含其他组件,我们有一个包含层次结构。在文档中,我们有时会讨论父组件和子组件。父组件包含子组件。父组件可以是所有者,也可以是容器。

设置子组件的属性

若要向下通信包含层次结构,所有者可以在子组件上设置属性。HTML 中的属性变成了 JavaScript 中的属性赋值。

父组件可以在子组件上设置基元值,如字符串或数字。但是,传递给组件的对象或数组等非原始值是只读的,您必须进行浅拷贝才能修改任何嵌套值。

在子组件上设置基元值

让我们看一下所有者 , 如何在 的两个实例上设置公共属性。c-todo-appc-todo-item

看。修饰器将字段公开为公共属性。todoItem.js@apiitemName

// todoItem.js
import { LightningElement, api } from "lwc";
export default class TodoItem extends LightningElement {
  @api itemName;
}

若要设置公共属性,请在每个组件上设置该属性。itemNametodoApp.htmlitem-namec-todo-item

<!-- todoApp.html -->
<template>
  <c-todo-item item-name="Milk"></c-todo-item>
  <c-todo-item item-name="Bread"></c-todo-item>
</template>

JavaScript 中的属性名称采用驼峰大小写,而 HTML 属性名称采用烤肉串大小写(破折号分隔)以匹配 HTML 标准。在 中,标记中的属性映射到 的 JavaScript 属性。todoApp.htmlitem-nameitemNamec-todo-item

提示

此示例使用 和 的静态值,但实际组件通常会对所有者的 JavaScript 文件 .MilkBreadfor:eachtodoApp.js

有关稍微复杂的示例,请参阅 lwc-recipes 存储库中的组合基本配方。

您还可以在 lwc.dev 的 Playground 中使用类似的代码,这是 Lightning Web 组件:开源开发人员网站。

在子组件上设置非基元值

传递给组件的非基元值(如对象或数组)是只读的。若要更改数据,请创建要更改的对象的浅拷贝。

让我们看一个父组件,它将对象传递给子组件,然后让子组件更新其值。

<!-- parent.html -->
<template>
  <div>Parent: {serializedObj}</div>
  <c-child obj="{obj}"></c-child>
</template>

在 JavaScript 中设置值。

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

export default class Parent extends LightningElement {
  obj = {
    msg: "hello",
  };

  get serializedObj() {
    return JSON.stringify(this.obj);
  }
}

反应式对象从父组件传递到子组件。子组件显示带有两个按钮的序列化对象字符串,这两个按钮通过更新原始对象或其浅表副本来更新对象值。obj

<!-- child.html -->
<template>
  <div>Child: {serializedObj}</div>

  <button onclick="{updateOriginal}">Update original</button>
  <button onclick="{updateShallow}">Update shallow</button>
</template>

该组件无法更改对象或数组的内容。当您尝试更新原始对象值时,会引发错误,因为子组件正在尝试改变对象上的属性。Uncaught Error: Invalid mutation: Cannot set "msg" on "[object Object]". "[object Object]" is read-only.

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

export default class Child extends LightningElement {
  @api obj;

  get serializedObj() {
    return JSON.stringify(this.obj);
  }

  updateOriginal() {
    this.obj.msg += "!!!"; // throws an invalid mutation error
  }

  updateShallow() {
    this.obj = { ...this.obj, msg: this.obj.msg + "!" };
  }
}

具有来自父组件的引用的非基元值(如 所示)包装在代理中,无法修改。但是,您可以通过创建非基元的浅拷贝来修改其内容。this.obj

当抛出无效的突变错误时,值赋值仅更新子组件上的值。父组件上的值不会更新。this.obj.msgthis.objupdateShallow(){serializedObj}{serializedObj}

数据流

为了防止代码复杂性和意外的副作用,数据应该沿一个方向流动,从父级流向子级。

当组件修饰字段以将其公开为公共属性时,它应该仅在初始化字段时设置该值。初始化字段后,只有所有者组件才能设置该值。组件应将传递给它的值视为只读。@api

若要触发所有者组件提供的属性值的突变,子组件可以向父组件发送事件。如果父级拥有数据,则父级可以更改属性值,该属性值通过单向数据绑定向下传播到子组件。

传递给组件的对象是只读的

传递给组件的非基元值(如对象或数组)是只读的。该组件无法更改对象或数组的内容。如果组件尝试更改内容,您会在浏览器控制台中看到错误:Uncaught Error: Invalid mutation: Cannot set "msg" on "[object Object]". "[object Object]" is read-only.

若要更改数据,请创建要更改的对象的浅拷贝。让我们看一下更新对象值的组件。

<!-- myCmp.html -->
<template>
  <p>{serializedObj}</p>
  <button onclick="{updateShallowCopy}">Update</button>
</template>

创建对象的浅拷贝,该拷贝仅复制顶级属性。不会复制嵌套对象的值。在此示例中,更新为单击按钮时。{"msg":"hello"}{"msg":"hello!"}

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

export default class extends LightningElement {
  obj = {
    msg: "hello",
  };

  get serializedObj() {
    return JSON.stringify(this.obj);
  }

  updateShallowCopy() {
    this.obj = { ...this.obj, msg: this.obj.msg + "!" };
  }
}

也可以使用 重新分配对象的值。该组件拥有该字段,并且可以为该字段分配一个新值。相反,如果组件尝试使用 更改对象上的嵌套值,则会在 Web 控制台中收到无效的突变错误。this.obj = { msg: 'My new message' }myCmpobjthis.obj.msg = 'new value'

同样,具有来自父组件的引用的非基元值包装在代理中,并且无法修改。请参见设置子组件的属性。

若要触发所有者组件提供的属性值的突变,组件应向所有者发送事件。

对公共属性使用基元值

建议对属性使用基元数据类型,而不是使用对象数据类型。在更高级别的组件中对复杂的数据结构进行切片,并将基元值传递给组件后代。

最好使用基元值有几个原因。

  • 基元值需要明确定义数据形状的特定属性。接受对象或数组需要文档来指定形状。如果对象形状发生变化,使用者就会中断。@api
  • 标准 HTML 元素仅接受属性的基元值。当标准 HTML 元素需要复杂形状时,它使用子组件。例如,元素使用 和 元素。只能在 HTML 中定义基元类型。例如,在 HTML 中不是值,而是在 Lightning Web 组件中。tabletrtd<table data={...}>

在子组件上调用方法

若要公开公共方法,请使用 .公共方法是组件 API 的一部分。若要在包含层次结构中向下通信,所有者和父组件可以在子组件上调用 JavaScript 方法。@api

注意

若要在包含层次结构中向上通信,请在子组件中触发事件,并在所有者或容器组件中处理该事件。请参阅与事件通信。

查看 lwc-recipes 存储库中的组件(以前命名为 ),该组件在其子组件上调用方法。apiMethodapiFunctionclock

定义方法

此示例通过向组件中添加装饰器来公开属性和 和方法的 getter。包含的父组件可以读取属性并调用方法。下面是 JavaScript 文件。isPlayingplay()pause()c-video-player@apic-video-player

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

export default class VideoPlayer extends LightningElement {
  @api videoUrl;

  @api
  get isPlaying() {
    const player = this.template.querySelector("video");
    return player !== null && player.paused === false;
  }

  @api
  play() {
    const player = this.template.querySelector("video");
    // the player might not be in the DOM just yet
    if (player) {
      player.play();
    }
  }

  @api
  pause() {
    const player = this.template.querySelector("video");
    if (player) {
      // the player might not be in the DOM just yet
      player.pause();
    }
  }

  // private getter for computed value
  get videoType() {
    return "video/" + this.videoUrl.split(".").pop();
  }
}

videoUrl是公共财产。装饰器可用于在组件上定义公共属性和公共 JavaScript 方法。公共属性是组件公共 API 的另一部分。@api

注意

若要访问模板拥有的元素,代码将使用 template 属性。

现在,让我们看一下定义 video 元素的 HTML 文件。

<!-- videoPlayer.html -->
<template>
  <div class="fancy-border">
    <video autoplay>
      <source src={videoUrl} type={videoType} />
    </video>
  </div>
</template>

在实际组件中,通常具有播放或暂停视频本身的控件。为了说明公共 API 的设计,此示例中控件位于调用公共方法的父组件中。c-video-player

调用方法

该组件包含并具有用于调用 中的 和 方法的按钮。下面是 HTML。c-method-callerc-video-playerplay()pause()c-video-player

<!-- methodCaller.html -->
<template>
  <div>
    <c-video-player video-url={video}></c-video-player>
    <button onclick={handlePlay}>Play</button>
    <button onclick={handlePause}>Pause</button>
  </div>
</template>

单击中的按钮将在我们连接 中的 和 方法后播放或暂停视频。c-method-callerc-video-playerhandlePlayhandlePausec-method-caller

下面是 的 JavaScript 文件。c-method-caller

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

export default class MethodCaller extends LightningElement {
  video = "https://www.w3schools.com/tags/movie.mp4";

  handlePlay() {
    this.template.querySelector("c-video-player").play();
  }

  handlePause() {
    this.template.querySelector("c-video-player").pause();
  }
}

中的函数调用元素中的方法。 返回 中的元素。该调用可用于访问子组件,以便可以在组件上调用方法。handlePlay()c-method-callerplay()c-video-playerthis.template.querySelector('c-video-player')c-video-playermethodCaller.htmlthis.template.querySelector()

中的函数调用元素中的方法。handlePause()c-method-callerpause()c-video-player

返回值

若要从 JavaScript 方法返回值,请使用该语句。例如,请参见中的方法。returnisPlaying()c-video-player

@api get isPlaying() {
    const player = this.template.querySelector('video');
    return player !== null && player.paused === false;
}

方法参数

若要将数据传递给 JavaScript 方法,请为该方法定义一个或多个参数。例如,您可以定义采用控制视频播放速度的参数的方法。play()speed

@api play(speed) { … }

查询选择器

该方法是一个标准的 DOM API,它返回与选择器匹配的第一个元素。querySelector()

如果要遍历数组,请考虑向元素添加一些其他属性,例如 或 value,并使用它来选择所需的元素。classdata-*

该方法返回一个 DOM 元素数组。querySelectorAll()

注意

不要将 传递给查询方法,例如 。呈现 HTML 模板时,可以将值转换为全局唯一值。如果在 JavaScript 中使用选择器,则它与转换后的 .idquerySelectorididid

有关详细信息,请参阅 developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll 和 developer.mozilla.org/en-US/docs/Web/API/Element/querySelector。

子组件上的 Spread 属性

使用指令将对象中的一组属性传递给子组件。 还使元素能够接受在运行时绑定为属性的对象。lwc:spreadlwc:spread

提示

lwc-recipes 存储库有一个演示指令的组件。apiSpreadlwc:spread

该指令接受一个对象。lwc:spread

<!-- app.html -->
<template>
  <c-child lwc:spread={childProps}></c-child>
</template>

使用具有键值对的对象,其中键是属性名称。

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

export default class extends LightningElement {
  childProps = { name: "James Smith", country: "USA" };
}

在子组件中,使用模板中的属性。

<!-- child.html -->
<template>
  <p>Name: {name}</p>
  <p>Country : {country}</p>
</template>

使用修饰器向父组件公开属性。@api

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

export default class Child extends LightningElement {
  @api name;
  @api country;
}

lwc:spread始终最后应用,因此它会覆盖模板中直接声明的任何属性。一个指令只能使用一个实例。lwc:spread

<!-- app.html -->
<template>
  <c-child name="lwc" lwc:spread={childProps}></c-child>
</template>

在此示例中,即使父组件传入,也要传递 。最终,子组件将采用该名称。c-childnameLightning Web Componentsname="lwc""lwc"

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

export default class extends LightningElement {
  childProps = { name: "Lightning Web Components" };
}

lwc:spread不将组件绑定到模板中定义的事件处理程序。例如,可以在对象中传入处理程序作为属性名称。onclick

<!-- app.html -->
<template>
  <c-child lwc:spread={simpleProps}></c-child>
</template>

在这里,作为 .单击 c-child 元素时,将替换为 。c-childnameLWCspreadClick()nameLightning Web Components

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

export default class extends LightningElement {
  simpleProps = { name: "LWC", onclick: this.spreadClick.bind(this) };
  spreadClick() {
    this.simpleProps = { name: "Lightning Web Components" };
  }
}

虽然我们没有包含在 中,但元素包含之前通过对象分配给它的元素。onclickspreadClick()onclicksimpleProps

在子组件上反映 HTML 属性

大多数 HTML 属性都反映为属性。例如,属性反映为属性。classclassName

假设您将属性传递给子组件。

<!-- app.html -->
<template>
  <c-child lwc:spread={spanProps}></c-child>
</template>

因此,该属性会导致元素呈现为 。spanProps<c-child class="spanclass" id="mySpan"></c-child>

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

export default class extends LightningElement {
  spanProps = { className: "spanclass", id: "myspan" };
}

将标记传递到插槽中

将槽添加到组件的 HTML 文件中,以便父组件可以将标记传递到组件中。一个组件可以有零个或多个插槽。

插槽 () 是父组件传递到组件主体中的标记的占位符。<slot></slot>

重要

您无法将 Aura 组件传递到插槽中。如果将 Lightning Web 组件嵌套在 Aura 组件中,则也无法将其传递到插槽中。

未命名插槽

此示例有一个未命名的插槽。未命名的插槽使用该元素作为父组件传递到 主体中的任何标记的占位符。<slot>c-slot-demo

<!-- slotDemo.html -->
<template>
  <h1>Add content to slot</h1>
  <div>
    <slot></slot>
  </div>
</template>

下面是使用 .c-slot-demo

<!-- slotWrapper.html -->
<template>
  <c-slot-demo>
    <p>content from parent</p>
  </c-slot-demo>
</template>

呈现时,未命名的插槽将替换为传递到 正文中的标记。下面是 的渲染输出。c-slot-democ-slot-democ-slot-wrapper

<h1>Add content to slot</h1>
<div>
  <slot>
    <p>content from parent</p>
  </slot>
</div>

如果组件具有多个未命名槽,则传递到组件主体中的标记将插入到所有未命名槽中。但是,一个组件通常有零个或一个未命名的插槽。

命名插槽

此示例组件有两个命名槽和一个未命名槽。

<!-- namedSlots.html -->
<template>
  <p>First Name: <slot name="firstName">Default first name</slot></p>
  <p>Last Name: <slot name="lastName">Default last name</slot></p>
  <p>Description: <slot>Default description</slot></p>
</template>

您可以为 HTML 元素的属性设置动态值。在这里,该元素的属性设置为变量 。slot<span>slotdynamicName

<template>
  <c-item>
    <span slot={dynamicName}></span>
  </c-item>
</template>

传递到属性中的动态值被强制转换为字符串。例如,如果将数字 4 传递给属性,则该属性将转换为字符串 。如果传入无法转换为字符串的数据类型(如 ),则会引发 TypeError。slot"4"Symbol()

此更改不会影响元素的属性。例如,您仍然必须将静态字符串传递到元素的属性中。<slot>name<slot>

<template>
  <slot name="”staticName”"> </slot>
</template>

下面是使用 .c-named-slots

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

该组件通过:c-slots-wrapper

  • Willy进入插槽firstName
  • Wonka进入插槽lastName
  • Chocolatier进入未命名的插槽

下面是呈现的输出。

<c-named-slots>
  <p>
    First Name:
    <slot name="firstName"><span slot="firstName">Willy</span></slot>
  </p>
  <p>
    Last Name:
    <slot name="lastName"><span slot="lastName">Wonka</span></slot>
  </p>
  <p>
    Description:
    <slot><span>Chocolatier</span></slot>
  </p>
</c-named-slots>

通过插槽传递的访问元素

该元素是组件影子树的一部分。要访问其影子树中的元素,组件将调用 和 .<slot></slot>this.template.querySelector()this.template.querySelectorAll()

但是,传递到插槽中的 DOM 元素不是组件影子树的一部分。要访问通过插槽传递的元素,组件将调用 和 .this.querySelector()this.querySelectorAll()

此示例演示如何将 DOM 元素从子组件的上下文传递给子组件。为 和 提供选择器名称,例如元素。this.querySelector()this.querySelectorAll()

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

export default class NamedSlots extends LightningElement {
  renderedCallback() {
    this.querySelector("span"); // <span>push the green button.</span>
    this.querySelectorAll("span"); // [<span>push the green button</span>, <span>push the red button</span>]
  }
}

在此示例中,接受元素 .querySelectorspan

注意

不要将 传递给查询方法,例如 。呈现 HTML 模板时,可以将值转换为全局唯一值。如果在 JavaScript 中使用选择器,则它与转换后的 .idquerySelectorididid

有条件地渲染插槽

要有条件地呈现插槽,请使用 、 和/或指令将插槽嵌套在标记中。<template>lwc:iflwc:elselwc:elseif

<template>
  <template lwc:if={expression}>
    <div class="my-class">
      <slot></slot>
    </div>
  </template>
  <template lwc:else>
    <slot></slot>
  </template>
</template>

模板编译器将条件指令视为有效的用例,并且知道不会呈现两次。<slot>

如果使用 legacy 和 指令,编译器会警告你重复的插槽,因为不清楚是否只会呈现一次。例如,getter 每次的返回值都可能不一致。if:trueif:false<slot>expression

在 slotchange 上运行代码

所有元素都支持该事件。当元素中节点的直接子节点发生更改时,将触发该事件。例如,当追加或删除新内容时,会发生这种情况。只有元素支持此事件。<slot>slotchangeslotchange<slot><slot>

元素的子元素中的更改不会触发事件。<slot>slotchange

在此示例中,元素处理事件。<slot>slotchange

<!-- container.html -->
<template>
  <slot onslotchange={handleSlotChange}></slot>
</template>
// container.js
handleSlotChange (e) {
   console.log("New slotted content has been added or removed!");
}

元件被传递到插槽中。c-child

<c-container>
  <c-child></c-child>
  <template lwc:if={addOneMore}>
    <c-child></c-child>
  </template>
</c-container>

如果该标志设置为 True,则控制台将在首次呈现组件时打印。addOneMore

<!-- child.html -->
<template>
  <button onclick={handleClick}>Toggle Footer</button>
  <template lwc:if={showFooter}>
    <footer>Footer content</footer>
  </template>
</template>

即使为 true 并且追加了页脚元素,也不会触发该事件。slotchangeshowFooter

使用插槽与数据组合组件

创建包含其他组件的组件时,请考虑组件层次结构的生命周期,使用带有槽的声明性方法,或数据驱动方法,其中子组件对其父组件的数据更改做出反应。

以声明方式构建组件的常见模式如下所示。

<c-parent>
  <c-custom-child></c-custom-child>
  <c-custom-child></c-custom-child>
</c-parent>

此示例具有使用元素的组件。尽管对使用者来说很方便,但您必须管理通过元素传递的内容的生命周期。c-parentslotslot

有几种方法可以管理传递到槽中的内容。

  • 使用 slotchange 事件。这是推荐的方法。 通过 DOM 向上冒泡,但不会越过阴影边界,从而使包含插槽的父组件能够对其做出反应。slotchange
  • 使用自定义事件将子组件的更改通知父组件,这使您能够将要与之交互的组件上的方法设为私有。我们不再建议使用此方法,因为我们正在逐步迁移组件以使用本机影子,这会强制组件使用该事件。slotchange

将 slotchange 事件与插槽一起使用

使用带有槽的事件,可以管理父组件和子组件之间内容的生命周期。此模式的一个示例是具有子组件的基本组件。slotchangeslotlightning-button-grouplightning-button

<lightning-button-group>
  <lightning-button label="Refresh"></lightning-button>
  <lightning-button label="Edit"></lightning-button>
  <lightning-button label="Save"></lightning-button>
</lightning-button-group>

父组件包含一个带有事件的元素,用于管理传入内容的生命周期。lightning-button-groupslotonslotchange

<!-- buttonGroup.html -->
<template>
  <slot onslotchange={handleSlotChange}></slot>
</template>

注意

基本组件示例仅用于演示目的。基本组件内部结构可能会发生变化。我们记录了对组件功能和行为的更改,但不记录对其内部的更改。有关基本组件的公共属性和方法,请参阅组件参考。

当槽的内容发生更改时,处理程序将处理对槽元素的更新。在这种情况下,父组件根据子组件在组中的显示顺序(第一个、中间、最后一个,或者它是否是组中的唯一按钮)来确定子组件上的 CSS 类。slotchangelightning-button-grouplightning-button

// buttonGroup.js
handleSlotChange(event) {
  const slot = event.target;
  const children = slot.assignedElements() || [];

  // Loop through each child and
  // set the order value based on position in the group
  this.updateGroupOrder(children); }

使用 getter 修改按钮类。

<!-- button.html -->
<template>
  <button class={computedButtonClass} ...>{label}</button>
</template>
// button.js
get computedButtonClass() {
    return classSet('slds-button')
    .add({
        // Other button classes here
        'slds-button_first': this._order === 'first',
        'slds-button_middle': this._order === 'middle',
        'slds-button_last': this._order === 'last'
    })
    .toString();
}

触发寄存器事件,以便组件可以注册组件。lightning-button-grouplightning-button

// button.js
connectedCallback() {
  this._connected = true;
    const privatebuttonregister = new CustomEvent('privatebuttonregister', {
        bubbles: true,
        detail: {
            callbacks: {
                setOrder: this.setOrder.bind(this),
                setDeRegistrationCallback: (deRegistrationCallback) => {
                    this._deRegistrationCallback = deRegistrationCallback;
                }
            }
        }
    });

    this.dispatchEvent(privatebuttonregister);
}

当子组件不再可用时通知父组件。

// button.js
disconnectedCallback() {
  this._connected = false;
  if (this._deRegistrationCallback) {
      this._deRegistrationCallback();
  }
}

使用数据驱动型方法

使用数据驱动的方法,当数据发生变化时,组件会以反应性方式获取更改。

此示例使用数据驱动方法编写子组件。

<template>
  <div class="c-parent">
    <template for:each={itemsData} for:item="itemData">
      <c-child onclick={onItemSelect} id={itemData.id} key={itemData.id}> </c-child>
    </template>
  </div>
</template>

若要传入数据,请使用 JavaScript 对象。子组件仅对来自其父组件的数据更改做出反应。

itemsData = [
    {
        label : 'custom label 1',
        id : 'custom-id-1'
        selected : false
    },
    {
        label : 'custom label 2',
        id : 'custom-id-2'
        selected : false
    }
]

当您有复杂的用例时,建议采用数据驱动的方法。使用数据驱动方法创建的基本组件的一个示例是 lightning-datatable

查看组件依赖关系

使用依赖项树查看器可查看组件使用的自定义组件和 Apex 类。您可以快速查看组件的结构并导航到其依赖项的源。

在“设置”的“快速查找”框中,输入 ,然后选择 Lightning 组件Lightning Components

  • 要在详细信息页面上查看 Lightning Web 组件的依赖关系,请单击其名称旁边的 V 形图标,展开 Lightning Web 组件行。
  • 若要查看其中一个依赖项的详细信息,请单击“名称”列中的链接。
查看组件依赖关系树

依赖关系树显示组件的最多三个级别的依赖关系。例如,您可以看到一个组件及其嵌套的子组件、孙子组件和曾孙子组件。若要查看更深层次的依赖项,请单击其中一个嵌套组件的“名称”列中的链接。

Lightning CSS

要为您的组件提供 Lightning Experience 外观,请使用 Lightning Design System。要走自己的路,请编写自己的 CSS。

使用 Lightning Design System 设置组件样式

Salesforce Lightning Design System (SLDS) 是一个 CSS 框架,可提供与 Lightning Experience 一致的外观。使用 SLDS 样式为您的自定义 Lightning Web 组件提供与 Salesforce 一致的 UI,而无需对我们的样式进行逆向工程。最重要的是,它只适用于在 Lightning Experience 和 Salesforce 移动应用程序中运行的 Lightning 组件。

提示

交互式基本组件示例可在组件参考中找到。

使用基本 Lightning 组件

命名空间中的基本组件使用 Lightning Design System 样式。许多基本组件都是根据 SLDS 组件蓝图构建的。蓝图与框架无关,可访问 HTML 和 CSS。一些示例包括 、 和 组件。lightninglightning-accordionlightning-cardlightning-tree

基本组件提供了一个属性,以便您可以将 SLDS 实用程序类或定制类添加到组件的外部元素中。例如,要将边距实用程序类应用于基本组件,请使用 。这里它用于增加按钮之间的边距。classlightning-buttonclass="slds-m-left_medium"

<template>
  <lightning-button label="Submit" title="submit" onclick={handleSubmit}></lightning-button>
  <lightning-button
    variant="brand"
    label="Cancel"
    title="cancel"
    onclick={handleCancel}
    class="slds-m-left_medium"
  ></lightning-button>
</template>

某些组件提供属性,以便您可以轻松地应用设计变体。variant

重要

在设置组件样式时,不要依赖基本 Lightning 组件的内部标记或 CSS 类,因为它们可能会在将来的版本中更改。不支持覆盖基本组件样式,除非使用记录的样式挂钩。请参阅样式组件的反模式。

使用基本 Lightning 组件设计变体和实用程序类

要更改基本 Lightning 组件的样式,请首先检查“组件参考”以查看该组件是否有设计变体。要更改组件的间距,例如对齐方式、填充、边距甚至其排版,请使用 Lightning Design System 实用程序类。

使用样式挂钩覆盖默认样式

如果设计变体和实用程序类不符合您的要求,请考虑设置挂钩样式。有关更多信息,请参阅使用 Lightning Design System 样式挂钩设置组件样式。

应用自定义 CSS类

如果样式挂钩不适用于您的用例,请尝试使用具有全局访问权限的设计令牌。

提示

从 24 年冬季开始,我们建议您尽可能使用全局颜色样式挂钩而不是设计标记,以符合 Web 内容可访问性指南 (WCAG) 2.1 颜色对比度标准。请参阅 Lightning Design System:迁移指南。

如果全局设计标记不起作用,请创建自定义 CSS 类,而不是重写 SLDS 类。创建一个类,而不是以您不拥有的类名为目标,因为该类名可能会更改。例如,不要以 为目标,因为它是基本组件内部标记的一部分。相反,创建一个自定义类并将其传递到 class 属性中。.slds-input

位于 Lightning Experience 或 Salesforce 移动应用程序中的自定义组件可以在没有任何语句或静态资源的情况下使用 Lightning Design System。只需将 Lightning Design System CSS 类分配给 HTML 元素即可。import

/* Do this */
.my-custom-styles {
  padding: var(--lwc-spacingMedium); /* --lwc-spacingMedium: 16px; */
}

/* DON’T DO THIS */
.slds-button {
  padding: 16px;
}

以增量方式应用样式。

/* Do this */
.my-style {
  padding: var(--scoped-spacing);
}

/* DON’T DO THIS */
.slds-scoped-notification {
  padding: var(--scoped-spacing);
}
<div class="slds-scoped-notification my-style"></div>

养成良好的CSS习惯,不要让选择器过载。

/* Don’t do this */
button.button {
  ...;
}
.card > * {
  ...;
}
.button {
  margin-bottom: 18px !important;
}
body.container > div.sidebar > article.card {
  ...;
}

从基础组件创建自定义组件

要构建 Lightning Web 组件,请通过将较小的基本组件组合成一个更复杂的自定义组件来组合它。尝试从按钮和媒体对象等组件构建您的设计。使用实用程序(例如网格和间距类)进行布局。当您向组件添加新功能时,请在 Lightning Design System 中搜索有效的模式,并将这些类应用于模板。lightning

例如,使用实用程序类更改标头大小或向容器添加填充。div

<template>
  <h1 class="slds-text-heading_large">SLDS Example</h1>
  <div class="slds-p-top_medium">
    <p>Hello!</p>
  </div>
</template>

从 Lightning Design 系统蓝图创建自定义组件

如果您找不到适合您的用例的基本组件,请找到最接近的 SLDS 蓝图来帮助您构建组件。请参见从 SLDS 蓝图创建组件。

使用基本 Lightning 组件设计变体

许多基本的 Lightning 组件都有多种设计变体。每个设计变体都赋予组件不同的外观。

基础组件设计变体对应于闪电设计系统 (SLDS) 中的变体。例如,支持将不同文本和背景颜色应用于按钮的设计变体。lightning-button

如果组件具有设计变体,则该组件具有属性。使用该属性选取设计变体。variantvariant

本示例创建一个具有设计变体的按钮,该按钮在按钮上提供蓝色背景色。brand

<lightning-button
  variant="brand"
  label="Submit"
  title="submit form"
  onclick={handleClick}
></lightning-button>

如果未指定 ,或者指定了不支持的值,则使用默认值。对于 ,缺省值为 。variantlightning-buttonneutral

如果您没有看到您喜欢的设计变体,或者组件没有属性,请使用 Lightning Design System 类来实现您想要的样式。variant

例如,要将边距实用程序类应用于基本组件,请使用 。lightning-buttonclass="slds-m-left_medium"

<lightning-button
  variant="brand"
  label="Submit"
  title="submit"
  onclick={handleSubmit}
  class="slds-m-left_medium"
></lightning-button>

还可以将实用工具类应用于嵌套在某些基本组件中的元素,如以下示例所示。基本组件的主体使用填充实用程序类。lightning-cardslds-p-horizontal_small

<lightning-card title="Hello">
  <lightning-button label="New" slot="actions"></lightning-button>
  <p class="slds-p-horizontal_small">Card Body (custom component)</p>
  <p slot="footer">Card Footer</p>
</lightning-card>

如果找不到合适的设计变体或 SLDS 类,请考虑使用样式挂钩。

提示

在“组件参考”中查看基本组件的设计变体和交互式示例。

使用 Lightning Design System 样式钩子设置组件样式

借助 Salesforce Lightning Design System (SLDS) 样式挂钩,可以轻松自定义组件样式并表达您的品牌。样式挂钩提供与 SLDS 组件蓝图和设计变体相对应的 CSS 自定义属性。要自定义 SLDS 样式,请在组件的样式表中声明相应的自定义属性。您可以使用自定义属性来设置基本组件和自定义组件的样式。

提示

要更改基本 Lightning 组件的样式,请首先检查该组件是否有设计变体。要更改组件的间距,例如对齐方式、填充、边距,甚至其排版,请查看 Lightning Design System 实用程序类。如果这些技术不适用于您的用例,请尝试 SLDS 样式挂钩。

样式钩子是 SLDS 样式表中的占位符,例如,它使您能够使用相应的 CSS 自定义属性来自定义样式。var(--slds-c-badge--color-background, #ecebea)--slds-c-badge-color-background

CSS 定制属性对应于 SLDS 组件蓝图及其设计变体。例如,自定义属性与具有品牌变体的按钮蓝图相对应。--slds-c-button-brand-*

组件级与全局颜色样式挂钩

组件级样式挂钩 () 使您能够更新特定组件中的属性。例如,若要将较粗的边框应用于单个按钮,请编辑该按钮的组件挂钩,它不会影响任何其他组件。请参阅 Lightning Design System: Styling Hooks。--slds-c-*

全局颜色样式挂钩 () 是预定义的值,用于在应用中全局使用。例如,若要重新命名应用程序,请使用全局挂钩对正在使用的所有组件进行更改。请参阅 Lightning Design System: Global Color Styling Hooks。--slds-g-*

我们建议您进行的任何颜色自定义都符合 Web 内容辅助功能指南 (WCAG) 2.1 文本和非文本颜色对比度标准。请参阅 Lightning Design System:迁移指南。

组件级样式钩子示例

让我们看一个 Lightning Web 组件,该组件实现了带有品牌变体的 SLDS 按钮蓝图,该蓝图将背景颜色转换为标准 Salesforce 蓝色。

<!-- myButton.html -->
<template>
  <button class="slds-button slds-button_brand">Submit</button></div>
</template>

重要

不要直接覆盖 SLDS 类,如本示例所示。

/* myButton.css */
/* Anti-pattern - Don't do this */
.slds-button_brand {
  background-color: purple;
}

不支持 CSS 覆盖,因为 SLDS 类和基本组件内部结构在将来的发行版中可能会更改。替代可能会过时,不再按预期工作。

请改用 CSS 自定义属性,如下例所示。

要对品牌变体应用不同的背景颜色,请指定相应的 CSS 自定义属性,即 。要使用自定义样式定位组件中的所有元素,请使用 :host 选择器。--slds-c-button-brand-color-background

/* myButton.css */
:host {
  --slds-c-button-brand-color-background: purple;
  --slds-c-button-brand-color-border: purple;
  /* Other CSS custom properties here */
}

或者,您可以使用其他选择器(如元素或自定义类)来限定自定义范围。

基本组件实现 SLDS 组件蓝图并使用 SLDS 样式。要在基本组件(如 )上自定义 SLDS 样式,请使用相应的 CSS 自定义属性。lightning-button

<!-- myBaseButton.html -->
<template>
  <lightning-button variant="brand" label="Submit" onclick={handleClick}></lightning-button>
</template>
/* myBaseButton.css */
:host {
  --slds-c-button-brand-color-background: orange;
  --slds-c-button-brand-color-border: orange;
  /* Other CSS custom properties here */
}

注意

有关样式挂钩的完整列表,请参阅每个组件的蓝图。例如,Buttons 样式挂钩列在 lightningdesignsystem.com/components/buttons/#Styling-Hooks-Overview 中。若要了解有关设置挂钩样式的详细信息,请参阅 lightningdesignsystem.com/platforms/lightning/styling-hooks/。

支持限制

组件蓝图

这些 Lightning Design System 组件蓝图及其 CSS 自定义属性在基础组件上不受支持。

  • 模态 – 模态组件蓝图与基础组件不对应。
  • Toast – 模块不支持自定义属性。lightning/platformShowToastEvent--slds-c-toast-*
  • 工具提示 – 组件不支持自定义属性。lightning-helptext--slds-c-tooltip-*

链接

不支持使用自定义属性设置链接的样式。链接用于基本组件(如 和)和模块中。lightning-breadcrumblightning-formatted-*lightning/navigation表单元素

不支持使用自定义属性设置表单元素的样式。表单元素用于,,,组件中。lightning-input-*lightning-checkbox-grouplightning-radio-grouplightning-textarea

助您构建自己的自定义组件。

首先,我们假设您已经用尽了“组件引用”中可用的基本组件列表,并且您无法使用样式挂钩自定义基本组件上的样式以满足您的要求。

要从 SLDS 蓝图构建组件,请搜索 SLDS 蓝图目录以查找最接近您的组件的设计。如果 SLDS 蓝图具有相应的基本组件,则该蓝图在页面右上角有一个 Lightning 组件按钮 (1)。每个蓝图都提供了其设备支持 (2) 的详细信息 – 自适应、响应式或仅限桌面。自适应蓝图具有非桌面断点的标记,而响应式蓝图则可跨屏幕大小优雅地缩放。

尽管基本组件实现了 SLDS 样式,但并非所有基本组件都支持移动屏幕。基本组件文档中列出了支持。

例如,数据表 SLDS 蓝图是自适应的,但基本组件不支持移动设备。此外,请考虑自适应选项卡 SLDS 蓝图,其中选项卡在移动屏幕上堆叠并充当按钮。相应的不支持此移动行为。lightning-datatablelightning-tabset

从基本变化开始

假设您要创建一个作用域通知,并且您知道没有相应的 Lightning Web 组件。从 SLDS 蓝图上的基本变体开始,然后从那里开始构建。首先,将响应式基本变体标记复制并粘贴到模板中。

<template>
  <div
    class="slds-scoped-notification slds-media slds-media_center slds-scoped-notification_light"
    role="status"
  >
    <div class="slds-media__figure">
      <span class="slds-icon_container slds-icon-utility-info" title="information">
        <svg class="slds-icon slds-icon_small slds-icon-text-default" aria-hidden="true">
          <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#info"></use>
        </svg>
        <span class="slds-assistive-text">information</span>
      </span>
    </div>
    <div class="slds-media__body">
      <p>
        It looks as if duplicates exist for this lead.
        <a href="javascript:void(0);">View Duplicates.</a>
      </p>
    </div>
  </div>
</template>

通知在标记中包含一个图标。将图标替换为基本组件。svg<div class="slds-media__figure">lightning-icon

<template>
  <div
    class="slds-scoped-notification slds-media slds-media_center slds-scoped-notification_light"
    role="status"
  >
    <div class="slds-media__figure">
      <lightning-icon
        icon-name="utility:info"
        alternative-text="information"
        size="small"
      ></lightning-icon>
    </div>
    <div class="slds-media__body">
      <p>
        It looks as if duplicates exist for this lead.
        <a href="javascript:void(0);">View Duplicates.</a>
      </p>
    </div>
  </div>
</template>

将消息移动到组件的 JavaScript 文件,并将属性绑定到模板。message

<template>
  <div
    class="slds-scoped-notification slds-media slds-media_center slds-scoped-notification_light"
    role="status"
  >
    <div class="slds-media__figure">
      <lightning-icon
        icon-name="utility:info"
        alternative-text="information"
        size="small"
      ></lightning-icon>
    </div>
    <div class="slds-media__body">
      <p>{message}</p>
    </div>
  </div>
</template>
import { LightningElement, api } from "lwc";

export default class ScopedNotification extends LightningElement {
  @api message = "It looks as if duplicates exist ...";
}

创建样式主题和变体

作用域通知蓝图包括要在组件中捕获的不同主题(浅色和深色)。使用 getter 函数返回所选主题的类名。

import { LightningElement, api } from "lwc";

export default class ScopedNotification extends LightningElement {
  @api message = "Your message here";
  @api theme = "";

  get scopedNotificationClass() {
    let className = "slds-scoped-notification slds-media slds-media_center";
    if (this.theme === "light") {
      className += " slds-scoped-notification_light";
    }
    if (this.theme === "dark") {
      className += " slds-scoped-notification_dark";
    }
    return className;
  }
}

更改主题时,图标样式会更改。深色主题使用反向变体。添加一个 getter 以返回正确的变体。

get iconVariant() {
  let iconVariant = null;

  if (this.theme == 'dark') {
    iconVariant = 'inverse';
  }

  return iconVariant;
}

更新标记,使其根据您使用的主题进行调整。从蓝图中修改此静态标记以使用动态样式。

<div
  class="slds-scoped-notification
    slds-media
    slds-media_center
    slds-scoped-notification_light"
  role="status"
></div>

将模板中的类绑定到 getter。scopedNotificationClass

<div class={scopedNotificationClass} role="status"></div>

同样,将 variant 属性绑定到 getter。lightning-iconiconVariant

<lightning-icon
  icon-name="utility:info"
  alternative-text="information"
  size="small"
  variant={iconVariant}
></lightning-icon>

实现组件

您的组件已准备好开始操作。您可以在其他组件中使用它,也可以将其包含在 Lightning 应用程序生成器的页面上。

此示例使用另一个 Lightning Web 组件中的组件。该示例提供响应式网格布局,并与 Tabs SLDS 蓝图相对应。c-scoped-notificationlightning-layoutlightning-tabset

<lightning-card>
  <lightning-layout multiple-rows>
    <lightning-layout-item size="12" small-device-size="9" padding="around-small">
      <lightning-tabset>
        <lightning-tab label="Item one">
          <div class="slds-m-bottom_small">
            <c-scoped-notification message="Hello notification!" theme="light">
            </c-scoped-notification>
          </div>
        </lightning-tab>
        <lightning-tab label="Item two"> Tab 2 content here </lightning-tab>
      </lightning-tabset>
    </lightning-layout-item>
    <lightning-layout-item size="12" small-device-size="3" padding="around-small">
      <p>Sidebar Content Goes Here</p>
    </lightning-layout-item>
  </lightning-layout>
</lightning-card>

由于我们指定 ,第一个中的内容占据了平板电脑或台式机上屏幕宽度的 75%(480 px 或更响应的断点)。在移动设备上查看时,将内容调整为占据屏幕宽度的 100%。请参阅创建响应式布局。small-device-size="9"lightning-layout-itemsize="12"

使用 Lightning Design System Design 令牌

设计标记是存储视觉设计属性的命名实体,例如边距和间距值、字体大小和系列或颜色的十六进制值。

提示

从 24 年冬季开始,我们建议您尽可能使用全局颜色样式挂钩而不是设计标记,以符合 Web 内容可访问性指南 (WCAG) 2.1 颜色对比度标准。请参阅 Lightning Design System:迁移指南。

在 Lightning Web 组件中使用 CSS 变量来访问 Lightning Design System 设计令牌。Lightning Web 组件可以使用任何标记为“全局访问”的 Lightning 设计系统设计令牌。

重要

如果收到错误:,则可能是您使用的令牌未标记为“全局访问”。使用全局令牌或使用自定义 Aura 设计令牌。No TOKEN named {tokenName} found

要在 Lightning Web 组件的 CSS 中引用设计令牌,请使用前缀并引用 中的令牌名称。--lwc-camelCase

/* myWebComponent.css */
div {
  margin-right: var(--lwc-spacingSmall);
}

注意

在编译时,我们将变量替换为它们的实际值,这意味着在运行时,对变量的引用不起作用。例如,不能使用标准 API 或变量。CSSStyleDeclaration.getPropertyValue()CSSStyleDeclaration.setPropertyValue()

使用自定义 Aura Token

Lightning Web 组件的 CSS 文件可以使用在您的组织中创建或从非托管软件包安装的自定义 Aura 令牌。

将视觉设计的基本价值捕获到自定义 Aura Token中。定义一次令牌值,然后在 Lightning 组件的 CSS 中重复使用它。令牌可以轻松确保您的设计保持一致,甚至更容易随着设计的发展而更新设计。

提示

从 24 年冬季开始,我们建议您尽可能使用全局颜色样式挂钩而不是自定义 Aura 令牌,以符合 Web 内容可访问性指南 (WCAG) 2.1 颜色对比度标准。请参阅 Lightning Design System:迁移指南。

通过创建 Lightning Token捆绑包,在开发者控制台中创建自定义 Aura Token。例如,此令牌捆绑包具有一个名为 的自定义 Aura 令牌。myBackgroundColor

<aura:tokens>
  <aura:token name="myBackgroundColor" value="#f4f6f9" />
</aura:tokens>

自定义 Aura 令牌并不新鲜,但现在您可以使用标准 CSS 函数在 Lightning Web 组件的 CSS 文件中使用它们。在自定义 Aura 令牌之前添加。var()--c-

/* myLightningWebComponent.css */
color: var(--c-myBackgroundColor);

使用 CSS 样式表设置组件样式
若要将一组样式与组件捆绑在一起,请在组件的文件夹中创建一个与组件同名的样式表。样式表将自动应用于组件。如果要使用一个或多个样式表设置组件的样式,请配置 static 属性。stylesheets

一个组件的文件夹中只能有一个样式表。样式表使用标准的 CSS 语法,您可以使用大多数选择器。样式表可以从多个 CSS 模块导入样式规则。

在组件的样式表中定义的样式的范围限定为该组件。此规则允许组件在不同的上下文中重用,而不会丢失其样式。它还可以防止组件的样式覆盖页面其他部分的样式。

深入探讨:Lightning Web 组件中的影子 DOM 和 CSS

此示例演示了在父组件中定义的 CSS 样式如何无法进入子组件。有两个组件,以及 .每个组件都包含一个标记。样式表将样式定义为 。运行代码时,样式仅适用于父级中的标记,而不适用于嵌套子级中的标记。c-parentc-child<h1>parent.cssh1xx-large<h1><h1>

<!-- parent.html -->
<template>
  <h1>To Do List (h1)</h1>
  <c-child></c-child>
</template>
/* parent.css */
h1 {
  font-size: xx-large;
}
<!-- child.html -->
<template>
  <h1>To Do Item (h1)</h1>
</template>
Parent text is extra large. Child text is normal size.

父组件可以设置子组件的样式,但它将其样式设置为单个元素。父母不能接触孩子。让我们添加一个选择器,用于定义子组件周围的边框。c-childparent.css

/* parent.css */
h1 {
  font-size: xx-large;
}

c-child {
  display: block;
  border: 2px solid red;
}
The child component has a red box around it. 

现在,让我们从组件自己的样式表 .c-childchild.css

在添加选择器之前,让我们先删除选择器以删除红色框。从组件及其父级设置组件样式不是一个好的做法,因为它可能会造成混淆并产生意外的结果。这是删除的。child.cssc-childparent.cssparent.cssc-child

/* parent.css */
h1 {
  font-size: xx-large;
}
组件的样式表可以到达并设置其自己的元素的样式,在此示例中为 .c-child

不要使用选择器,而应使用 :host 选择器。c-child

/* child.css */
:host {
  display: block;
  background: yellow;
}
Child component's background is yellow.

通过使用 以 host 元素为目标,我们已将样式应用于 ,from 。:host<c-child>child.css

选择器接受可选的选择器列表。若要匹配,主机元素必须具有与传递的选择器匹配的类。为了了解选择器的工作原理,让我们重写示例代码,使其看起来更像一个真正的应用程序。我们添加一个 to,以便我们可以在待办事项列表上传递项目的名称。:host:host<slot>c-child

<!-- child.html -->
<template>
  <h1>To Do Item</h1>
  <slot></slot>
</template>
让我们在子组件中设置样式,但要让它比我们在父组件中定义的要小一些。我们还将所有列表项设置为浅灰色,但活动项除外,该活动项为浅绿色。h1largexx-largeh1

/* child.css */
h1 {
  font-size: large;
}
:host {
  display: block;
  background: lightgray;
}

:host(.active) {
  background-color: lightgreen;
}
在父级中,让我们添加三个组件并使一个处于活动状态。在实际应用中,活动组件将是所选项目。c-child

<!-- parent.html -->
<template>
  <h1>To Do List</h1>
  <c-child>Buy potatoes</c-child>
  <c-child>Donate to a good cause</c-child>
  <c-child class="active">Plan a party</c-child>
</template>
/* parent.css */

h1 {
  font-size: xx-large;
}
To do list with active to do item in light green. 

CSS 支持和性能影响

CSS 作用域与 CSS 作用域模块级别 1 标准匹配,但有一些例外。

不支持 :host-context() 伪类函数。
不支持 ::p art 伪元素。
CSS 中不支持 ID 选择器。确保值在 HTML 模板中是唯一的。呈现模板时,值可能会转换为全局唯一值。如果在 CSS 中使用 ID 选择器,它将与转换后的 ID 不匹配。idid
LWC 不会将组件的自定义公共属性反映到其相应的 HTML 属性中。若要为子元素提供标识以进行样式设置,请使用属性或属性。classdata-*
作用域 CSS 会影响性能,因此请谨慎使用。每个选择器链都有作用域,传递给的每个复合表达式都分布到多个选择器中。这种转换增加了生成的 CSS 的大小和复杂性。这些增加意味着网络上的位数更多、解析时间更长、样式重新计算时间更长。:host()

为了确保 CSS 封装,每个元素都有一个额外的属性,这也增加了渲染时间。例如,元素具有属性。<c-parent>c-parent_parent-host

<c-parent c-parent_parent-host>
  <h1 c-parent_parent>To Do List</h1>
  <c-child c-parent_parent c-child_child-host>
    <h1 c-child_child>To Do Item</h1>
  </c-child>
  <c-child class="active" c-parent_parent c-child_child-host>
    <h1 c-child_child>To Do Item</h1>
  </c-child>
</c-parent>
将 CSS 样式表分配给组件

若要使用一个或多个样式表自定义组件,请将 static 属性添加到构造函数中。此属性接受样式表数组,其默认值为空数组。您可以设置光 DOM 和阴影 DOM 组件的属性。stylesheetsLightningElementstylesheets

例如,要将 和 样式表注入 ,请在 中配置 static 属性。header-styles.cssbutton-styles.cssmyComponentstylesheetsmyComponent.js

myComponent/
    ├── myComponent.js
    ├── myComponent.html
    ├── myComponent.css
    ├── header-styles.css
    └── button-styles.css
// myComponent.js
import { LightningElement } from 'lwc';
import headerStyles from './header-styles.css';
import buttonStyles from './button-styles.css';

export default Example class extends LightningElement {
    static stylesheets = [
        headerStyles,
        buttonStyles
    ];
}
LWC 引擎注入的第一个样式表是 ,因为它与组件的模板隐式关联。然后,引擎将按照数组中列出的顺序加载与该属性关联的所有样式表。根据 的此配置 ,按以下顺序加载其样式表:、 和 。myComponent.cssstylesheetsstylesheetsmyComponentmyComponent.cssheader-styles.cssbutton-styles.css

在组件类定义期间,LWC 引擎在应用程序的生存期内缓存数组。如果在评估组件代码后进行修改,则不会影响注入的样式表。stylesheetsstylesheets

子类组件不会自动从超类组件继承。如果要从超类组件扩展到子类组件,请使用手动将超类与子类组件的样式表合并。stylesheetsstylesheetssuper.stylesheetsstylesheets

import { LightningElement } from "lwc";
import superclassStylesheet from "./superclass.css";
import subclassStylesheet from "./subclass.css";

class Superclass extends LightningElement {
  static stylesheets = [superclassStylesheet];
}

class Subclass extends Superclass {
  static stylesheets = [...super.stylesheets, subclassStylesheet];
}

为组件创建样式挂钩

若要公开自定义组件的样式挂钩,请使用 CSS 自定义属性。CSS 自定义属性还使代码更易于阅读和更新。

将组件的样式钩子记录为组件 API 的一部分。要更改组件的样式,使用者只需设置样式钩子的值,他们不需要知道您如何实现样式。

使用公共属性设置 LWC 的样式

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

要在组件的样式表中定义 CSS 自定义属性,请在该属性前面加上前缀。要插入该属性的值,请使用 .--var()

:host {
  --important-color: red;
}

.important {
  color: var(--important-color);
}

CSS 自定义属性从其父组件继承其值。继承的属性刺穿了影子 DOM。一些 CSS 属性(如颜色)也是继承的。由于 CSS 自定义属性是继承的,因此使用者可以在 DOM 树中的更高级别设置其值并设置组件的样式。

这些 CSS 自定义属性为两个主题创建样式挂钩:浅色和深色。将回退值作为可选的第二个参数传递给 。var()

.light {
  background-color: var(--light-theme-background-color, lightcyan);
  color: var(--light-theme-text-color, darkblue);
}

.dark {
  background-color: var(--dark-theme-background-color, darkslategray);
  color: var(--dark-theme-text-color, ghostwhite);
}

在 lwc.dev 的 playgrounds 中试验此代码。

样式组件的反模式

以下是开发人员在设置 Lightning Web 组件样式时常犯的一些错误。这些技术不受支持,我们希望看到一些具体的例子对你有所帮助,这样你就可以避免它们。

最常见的反模式是根据 Lightning 基本组件的渲染标记设置样式,并直接覆盖 SLDS 类和样式。还应避免使用精确的类属性字符串匹配来查询元素。

反模式:设置基本组件的 HTML 样式

当你检查你的浏览器控制台并看到基本组件的渲染 HTML 时,很容易制作你的 CSS 来定位你看到的元素和类。但是,Salesforce 不支持基于呈现输出的样式。

Salesforce 需要灵活地重新设计组件的内部结构,以提高性能、增强功能并支持可访问性。因此,不能假定组件标记在版本上呈现相同的版本。如果基于这样的假设创建样式,则样式将来可能会中断。我们记录了对组件功能和行为的更改,但不记录对其内部的更改。

重要

不支持覆盖基本组件样式,除非使用记录的样式挂钩。

这是一个常见的错误,将 SLDS 类替换为您自己的类。

.myCustomClass .slds-class_name;

假设您的公司 Acme Widgets 在您的一个自定义组件中使用了基本组件。你用 Acme 自己的一个 SLDS 类替换一个 SLDS 类,因为它很方便,这是一个常见的错误。组件 CSS 以选择器为目标。lightning-combobox.slds-combobox__input

.acme-combobox_box .slds-combobox__input;

如果 Salesforce 更改为不再使用选择器,并且对 Acme 组件样式造成不利影响,则由您来修复组件的样式。lightning-combobox.slds-combobox__input

请参阅使用 Lightning Design System 设置组件样式,了解支持设置组件样式的方法。

反模式:覆盖 SLDS 类

获取 SLDS 选择器名称并稍作调整很简单,但不受支持。

覆盖 SLDS 选择器的属性时,将来对 SLDS 的更改可能会导致组件样式出现意外结果。Lightning Design System 不断改进,并将所有更改记录在 SLDS 发行说明中。

下面是一些不受支持的替代示例。

/* myButton.css */
/* Anti-pattern - Don't do this */
.slds-button_brand {
  background-color: purple;
}
/* Don’t do this */
.slds-button {
  padding: 16px;
}
/* Don’t do this */
.slds-scoped-notification {
  padding: var(--scoped-spacing);
}

请改用 Style Components with Lightning Design System 中讨论的技术。

反模式:具有精确属性字符串匹配的 querySelector

由于优化缩短了 Lightning Web 组件的渲染时间,静态节点的值和属性可能会使用额外的空格或意外字符进行渲染。更新使用类或样式属性的 JavaScript 代码,因为此更改可能会影响它们。styleclass

以前,您可以包含空格,以便通过使用精确的属性字符串匹配来使用元素的类名来查询元素。

/* Don’t do this */
document.querySelector('[class="highlight yellow"]');

该属性已呈现,如下所示。highlight yellow

<div class="highlight yellow">

但是,该属性现在可以使用额外的空格进行呈现。

<div class=" highlight yellow">

修改 JavaScript 代码以使用忽略空格的选择器。

/* Do this instead */
document.querySelector(".highlight.yellow");

反模式:依赖于生成的 CSS 范围令牌

为了在组件中限定 CSS 的范围,LWC 会自动向 DOM 元素添加属性和类。这些属性和类是内部实现细节,可以随时更改。

<c-cmp c-cmp_cmp-host>
  <span c-cmp_cmp></span>
</c-cmp>

虽然使用生成的类似于组件名称的 CSS 范围令牌很容易,但如果依赖于不拥有的组件的内部结构,则代码可能会中断。由于性能改进,LWC 为 Winter ’24 的 CSS 范围标记生成一个混淆字符串,格式为 ,其中是唯一的字母数字字符串。lwc-hashstringhashstring

<c-cmp lwc-2s44vctlls4-host>
  <span lwc-2s44vctlls4></span>
</c-cmp>

仅当升级到 LWC API 版本 59.0 时,为 CSS 范围令牌生成模糊处理字符串的更改才会影响您的自定义组件。但是,此更改会立即影响 Lightning Experience 和 Experience Builder 站点中 Salesforce 创作的组件,例如在记录页面或列表视图上呈现的组件,以及基本 Lightning 组件。

不要依赖代码中的内部属性和类,或使用 进行测试,因为内部实现可能随时更改。除了使用 ,您还可以使用模板 refs (lwc:ref)。this.template.querySelector()this.template.querySelector()

共享 CSS 样式规则

使用通用 CSS 模块为 Lightning Web 组件创建一致的外观。在 CSS 模块中定义样式,并将该模块导入到要共享样式的组件中。

您可以导入一个或多个 CSS 模块。导入的样式规则将应用于模板,就像未导入的样式规则一样。Lightning Web 组件支持 CSS 级联算法。

/* myComponent.css */

/* Syntax */
@import "namespace/moduleName";

/* Example */
@import "c/cssLibrary";

/* Note: Lightning web components can access modules only from the c and lightning namespaces
under Lightning Locker. If Lightning Web Security is enabled, Lightning web components 
can access modules from other namespaces. */

有关 的更多信息,请参阅 MDN Web 文档:@import。MDN 列出了两个语法语句:和 .LWC 不遵守 .@import@import {url}@import {url list-of-media-queries}{list-of-media-queries}

  1. 创建一个包含 CSS 文件和配置文件的 Lightning Web 组件。文件夹和文件名必须相同。这个组件是你的CSS模块。cssLibrary ├──cssLibrary.css └──cssLibrary.js-meta.xml
  2. 在 CSS 文件中定义样式规则。/* cssLibrary.css */ h1 { font-size: xx-large; }
  3. 配置文件只需要这些标记。<!-- cssLibrary.js-meta.xml --> <?xml version="1.0" encoding="UTF-8" ?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>49.0</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle>
  4. 在 Lightning Web 组件的 CSS 文件中,导入 CSS 模块。myComponent ├──myComponent.html ├──myComponent.js ├──myComponent.js-meta.xml └──myComponent.css/* myComponent.css */ @import "c/cssLibrary"; /* Define other style rules for myComponent here */
  5. 导入的样式规则将应用于模板,就像未导入的样式规则一样。所有样式规则级联。在模板中,标记中的文本使用 中定义的样式。myComponent.html<h1>xx-largecssLibrary.css<!-- myComponent.html --> <template> <h1>Words to the Wise</h1> <p>An apple a day keeps the doctor away.</p> </template>

提示

您可以在 lwc.dev/guide/css 的游乐场玩代码

创建 Lightning Web 组件

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:iffor:each

嵌套标记必须包含以下指令之一:、、或 。<template>for:eachiterator:iteratorNamelwc:iflwc:elselwc:elseifif: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(){}personperson.firstNameperson[2].name['John']

模板中使用的属性应包含基元值,但在 for:each 或迭代器指令中使用时除外。

示例:将组件模板属性绑定到 JavaScript 属性

若要在代码编辑器中继续操作,请打开 github.com/trailheadapps/lwc-recipes 存储库中的 、 和组件。您也可以将代码复制到 webcomponents.dev/create/lwc。hellohelloBindinghelloExpressions

下面是数据绑定的最简单示例。模板中的属性绑定到 JavaScript 类中的属性。greetinggreeting

<!-- 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-inputonchangehandleChangehandleChange{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 LIuppercasedFullName

模板中的属性绑定到 JavaScript 类中的 getter。uppercasedFullNameget 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 将名称组合并大写。handleChangefirstNamelastNameuppercasedFullName()

// 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:trueif:falselwc:if|elseif|else

此示例有两个属性和 。property1property2

<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。property1property2
  • Statement3呈现 if 和 are false。property1property2

尽管该示例使用所有三个指令,并且是可选的。lwc:elseiflwc:else

让我们看另一个例子。此模板包含一个标记为“显示详细信息”的复选框。当用户选中或取消选中该复选框时,该函数将设置属性的值。如果属性为 ,则该指令将呈现嵌套模板,该模板显示 These are the details!handleChangeareDetailsVisibleareDetailsVisibletruelwc: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:eachiterator<template>

该指令具有 和 属性,可用于将特殊行为应用于数组中的第一个和最后一个项目。iteratorfirstlast

无论使用哪个指令,都必须使用指令为每个项目分配唯一的 ID。当列表更改时,框架使用 仅重新呈现已更改的项。模板中的 用于性能优化,在运行时不会反映在 DOM 中。keykeykey

提示

若要在代码编辑器中继续操作,请打开 github.com/trailheadapps/lwc-recipes 存储库中的 和组件。还可以将代码复制到组件 IDE。helloForEachhelloIterator

适合:每个

使用该指令时,use 用于访问当前项目。此示例不使用它,但要访问当前项的索引,请使用 .for:eachfor: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",
    },
  ];
}

重要

列表中的每个项目都必须具有 .当列表更改时,框架使用 来标识每个项目,以便它只能重新呈现已更改的项目。必须是字符串或数字,不能是对象。不能用作 的值。为传入数据集分配唯一键。若要将新项添加到数据集,请使用私有属性来跟踪和生成键。keykeykeyindexkey

迭 代

若要将特殊行为应用于列表中的第一项或最后一项,请使用指令 。在标记上使用指令。iteratoriterator:iteratorName={array}iteratortemplate

使用 iteratorName 访问以下属性:

  • value– 列表中项目的值。使用此属性可访问数组的属性。例如。{iteratorName}.value.{propertyName}
  • index– 列表中项目的索引。
  • first– 一个布尔值,指示此项目是否为列表中的第一项。
  • last– 一个布尔值,指示此项目是否为列表中的最后一项。

此示例代码使用与上一个示例相同的数组。若要将特殊呈现应用于列表中的第一项和最后一项,代码将 and 属性与指令一起使用。firstlastlwc: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()

在此示例中,模板引用是 和 。templateOnetemplateTwo

// 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.htmltemplateTwo.cssmiscMultipleTemplates.csstemplateOne.css

MiscMultipleTemplates
   ├──miscMultipleTemplates.js
   ├──miscMultipleTemplates.js-meta.xml
   ├──templateOne.html
   ├──templateOne.css
   ├──templateTwo.html
   └──templateTwo.css

如果包含具有匹配名称的模板,则默认方法将返回该模板,除非包含上一示例中讨论的替代。miscMultipleTemplates.htmlrender()

提示

查看 lwc-recipes 存储库中的组件。miscMultipleTemplates

Lightning Web 组件入门

使用 Lightning Web 组件 (LWC) 框架在 Salesforce 平台上构建自定义用户界面、Web 和移动应用程序以及数字体验。Lightning Web 组件是使用 HTML 和 JavaScript 构建的自定义 HTML 元素。

Salesforce 提供基于 Lightning Design System 构建的基本 Lightning Web 组件,用作自定义体验的构建块。使用基本的 Lightning Web 组件为您的用户提供一致的外观,并简化您的开发体验。Salesforce Lightning Experience 基于 Lightning Design System 和基础 Lightning 组件构建。

提示

首先,请选择适合您的路径。

  • 开始编码:创建您的第一个组件
  • 设置开发环境
  • 探索 Trailhead 和示例代码
  • 了解如何使用 Salesforce 数据
  • 了解如何自定义 Salesforce 功能

编写标准的 JavaScript 和 HTML

Lightning Web 组件使用核心 Web 组件标准,并且仅提供在 Salesforce 支持的浏览器中正常运行所需的内容。由于 Lightning Web 组件基于在浏览器中本地运行的代码构建,因此它是轻量级的,可提供卓越的性能。您编写的大多数代码都是标准的 JavaScript 和 HTML。

Salesforce 致力于开发开放的 Web 标准,并且是万维网联盟 (W3C) 的成员。Salesforce 开发人员是 Ecma 国际技术委员会 39 (TC39) 的贡献成员,该委员会是发展 JavaScript 的委员会。

Lightning Web Components 也是开源的。

向后兼容性

您可以使用两种编程模型构建 Lightning 组件:Lightning Web 组件和原始模型 Aura 组件。Lightning Web 组件和 Aura 组件可以在一个页面上共存和互操作。对于管理员和最终用户来说,它们都显示为 Lightning 组件。

基础 Lightning 组件可作为 Lightning Web 组件和 Aura 组件使用。组件参考包括两者的文档、规格和示例。请参阅基本组件:Aura 与 Lightning Web 组件,了解它们之间的差异。

当您在 LWC 和 Aura 之间进行选择时,请选择 LWC。了解如何选择 Lightning Web 组件或 Aura。

Lightning 组件库

Lightning 组件库包括 Lightning Web Security 和 Lightning Locker 的组件参考信息和工具。

您可以在两个位置找到组件库:公共站点和链接到您的 Salesforce 组织的经过身份验证的站点。在经过身份验证的站点中,“组件库”的“组件引用”部分具有一些附加功能。公共组件库

在不登录 Salesforce 的情况下查看此站点。“组件参考”包括基本组件的文档和参考信息。

https://developer.salesforce.com/docs/component-library组织的组件库

通过登录您的 Salesforce 组织并导航到 来查看此站点。或者,单击公共站点右上角的“链接到您的组织”。https://<myDomainName>.lightning.force.com/docs/component-library

经过身份验证的站点具有组件引用的更多功能。

  • 查看您的组织独有的 Lightning 组件。
  • 查看安装在托管软件包中的 Lightning 组件。您可以进行筛选以查看您的组织拥有的组件或安装在软件包中的组件。

注意

《开发人员指南》在组件库中不再可用。访问会将您重定向到 。https://developer.salesforce.com/docs/component-library/documentation/en/lwchttps://developer.salesforce.com/docs/platform/lwc/guide

组件参考

在组件参考中,您可以找到有关每个基本 Lightning 组件的详细信息。它记录了 Lightning Web 组件和 Aura 编程模型的全套基本组件。

以下是有关组件参考的一些亮点。过滤器组件

在“概述”页上,筛选以重点关注你感兴趣的组件。例如,若要仅查看与导航相关的组件,请选择“筛选器”|”分类 |导航。查看目标

选择组件时,顶部的“目标”面板会显示可以使用该组件的位置。目标可以包括 Salesforce 应用程序、Lightning Experience、Experience Builder Sites、Salesforce 移动应用程序、独立 Lightning 应用程序等。在组件之间切换

通过单击“以 Aura 组件形式查看”和“以 Lightning Web 组件形式查看”按钮,在组件的版本之间切换。查看示例、文档和规格页面

大多数组件都有“示例”、“文档”和“规范”页面。某些组件(如 和)需要 Salesforce 数据。它们不能在组织外部使用,也没有示例页面。lightning-record-formlightning-input-field修改交互式示例

示例页包含交互式代码示例,用于演示组件的外观和行为。您可以查看正在运行的代码。对于 Lightning Web 组件,您还可以在 Lightning Mini Playground 中编辑示例代码,并立即在交互式示例中查看您的更改。但是,示例中使用的组件不是最新版本。请参阅组件参考示例。

组件引用的已知问题

以下是组件引用的一些已知问题。示例使用旧版本的基本 Lightning 组件和 Salesforce Lightning Design System (SLDS)

由于技术限制,示例的运行时环境不使用最新版本的组件和 SLDS。有关详细信息,请参阅组件参考示例。公共组件引用与经过身份验证的组件引用中的非闪电命名空间差异

在公共站点中,非 lightning 命名空间的组件参考可能包含过时的内容。对于非闪电组件(如 或),请验证 中的规格和文档。wave:waveDashboardforce:createRecordhttps://<myDomainName>.lightning.force.com/docs/component-library不支持在您的组织中开发的 Lightning Web 组件的文档

“组件参考”不显示自定义 Lightning Web 组件的文档规格面板缺少内容

模块不会在“规范”页上显示说明或方法。说明和方法位于文档页面上。模块包括:

  • lightning/empApi
  • lightning/flowSupport
  • lightning/messageService
  • lightning/navigation

某些具有默认值的属性不会在“默认”列中显示值。有关默认值,请参阅“说明”列。

自定义事件不会显示在“规范”页面中。有关此信息,请参阅组件的文档页面。不支持版本控制和本地化

组件参考不像其他 Salesforce 开发人员文档那样提供版本或语言选择器。它仅显示与当前版本相对应的文档,并且内容仅提供英文版本。

组件参考示例

“示例”选项卡显示在页面上的运行时环境中呈现的基本 Lightning 组件示例代码。

要试验 Lightning Web 组件示例,请修改代码并单击运行。Aura 组件示例不可编辑,但可以渲染,您可以与它们交互。

由于我们正在努力解决的技术限制,运行时环境不使用最新版本的基本 Lightning 组件。因此,组件更改(如最近版本中记录的新属性)不会反映在示例中,如果将它们添加到示例中,则不起作用。

运行时环境也跟不上 SLDS 版本。我们在 See Improved Color Contrast in UI Elements Winter ’24 发行说明中宣布的 Web 内容辅助功能指南 (WCAG) 颜色更新未反映在示例中。但是,您在自定义组件中使用并在 Salesforce 组织中运行的基本 Lightning 组件确实包含基本组件和 SLDS 的最新功能。

Lightning Web Security 控制台和 LWS 失真查看器工具

Lightning Web Security 控制台和 LWS 失真查看器可帮助您开发与 Lightning Web Security 一起运行的安全 JavaScript 代码。

有关使用这些工具的更多信息,请参阅在 Lightning Web Security 控制台中评估 JavaScript 和在 LWS 失真查看器中查找失真详细信息。

有关 Lightning Web Security 及其与 Lightning Locker 的比较的更多信息,请参阅 Lightning Web Security。

Locker 控制台和 Locker API 查看器工具

Locker 控制台和 Locker API 查看器可帮助您开发与 Lightning Locker 兼容并高效运行的安全 JavaScript 代码。

有关使用这些工具的更多信息,请参阅《Lightning Aura 组件开发人员指南》中的 Lightning Locker 工具。

有关 Lightning Locker 和 Lightning Web 组件的更多信息,请参阅 Lightning Locker 的安全性。

Lightning Web 组件发行说明

使用 Salesforce 发行说明了解 Lightning Web 组件的最新更新和更改。

有关影响 Lightning Web 组件的更新和更改,请参阅 Salesforce 发行说明中的 Lightning 组件。

有关新的和更改的组件和模块,请参阅 Salesforce 发行说明中的 Lightning 组件:新增和更改的项目。

开始编码

编写第一个 Lightning Web 组件代码的最快方法是使用实时代码环境。

要开始使用简单的组件,我们建议使用 LWC.studio 或 StackBlitz。或者,使用 Salesforce DX 工具将 LWC 代码推送到您的组织。

注意

StackBlitz 和 LWC.studio 是第三方产品,受其自身条款和条件的约束。Salesforce 对这些网站上提供的内容、服务或付费选项概不负责。您使用这些网站和平台的风险由您自行承担,并受任何适用的附加条款的约束,例如第三方的服务条款或隐私政策。

特定于基本组件的实时示例也可在 studio.webcomponents.dev/workspace/lwc 和组件参考中找到。

创建您的第一个组件

让我们使用 LWC.studio 中的第三方 IDE 创建一个 Hello World Lightning Web 组件。

  1. 在浏览器中,转到 app.lwc.studio。使用您的 GitHub 帐户登录。
  2. 登录后,单击“+新建”按钮。
  3. 通过单击文件夹旁边显示的“新建文件”图标来创建文件,并将其命名为 。将此代码复制到代码编辑器中。srchelloWorld.html
  4. 创建一个文件并将其命名为 。将此代码复制到代码编辑器中。helloWorld.js
  5. 若要查看组件,请将其添加到文件中最后一个结束标记之前。app.html</div>骆驼大小写组件名称 () 映射到 HTML () 中的烤肉串大小写。默认命名空间是 ,因此完整组件 HTML 标记是 。另请注意,组件必须使用结束标记。若要引用自己的组件,请始终使用默认命名空间 .无论代码在何处运行,都可以使用:在有或没有命名空间的组织中,在托管或非托管包中。helloWorldhello-worldc<c-hello-world>cc
  6. 要保存所有更改,请单击代码编辑器右上角的“保存”图标。“故事”面板将刷新以显示“Hello, World!”文本。
  7. 让我们更进一步,向组件添加一个公共属性。在 中,导入 ,并使用它来装饰字段。c-hello-worldhelloWorld.jsapifirstName
  8. 由于公开了公共属性,因此使用该属性的组件可以设置该属性。在我们的示例中,该组件设置了属性。c-hello-worldc-hello-worldappfirstName在 中,向标记添加属性。骆驼大小写 JavaScript 属性映射到 HTML 中的 kebab 大小写。app.htmlfirst-name<c-hello-world>firstNamefirst-name
  9. 现在,您的组件是可重用的。例如,您可以添加多个组件,并将每个组件设置为不同的值。c-hello-worldapp.html

若要继续编码,请跳转到模板中的数据绑定。玩得愉快!

Lightning Web 组件:开源

Lightning Web 组件是开源的,使您能够探索源代码,自定义行为以满足您的需求,并在任何平台(而不仅仅是 Salesforce)上构建企业级 Web 组件。

过去,您必须使用不同的框架来构建托管在 Salesforce 外部的应用程序的不同方面。例如,您使用 Aura 在 Salesforce 上构建应用程序面向员工的一面。您使用 React、Angular 或 Vue 构建了应用程序面向客户的端,并将其部署在 Heroku 或其他平台上。现在,您可以使用 Lightning Web 组件来构建应用程序的两端。好处是显着的。您现在可以学习一个框架而不是多个框架。您可以在应用之间共享代码。而且,您正在使用基于 Web 标准并基于最新模式和最佳实践构建的尖端框架。

  • GitHub 存储库 – github.com/salesforce/lwc
  • 开源开发人员站点 – lwc.dev

《Lightning Web 组件开发人员指南》(您现在正在阅读)介绍了如何开发在 Lightning 平台上运行的 Lightning Web 组件,以及如何使用 Lightning Data Service、Lightning Locker 和 Lightning Out 等平台功能。

与 Lightning Web 组件开源一样,Lightning Out 允许您在 Lightning Platform 上运行 Lightning Web 组件。如果您的组件需要访问 Salesforce 数据,请使用 Lightning Out。如果您的组件不需要 Salesforce 数据或任何其他 Salesforce 功能,请使用 Lightning Web Components 开源进行开发。

LWC 开源和 Salesforce 平台上的 LWC 之间的差异

重要

开源存储库中的代码领先于 Lightning 平台上可用的代码。开源存储库中发布的大多数功能最终都会在 Lightning 平台上发布。

Salesforce 平台上的 Lightning Web 组件是 Lightning Web 组件:开源的托管版本。在 Salesforce 平台上工作时,您可以下载 LWC,按照自己的方式进行配置,在任何托管环境中部署应用程序,并选择何时升级。在 Salesforce 平台上工作时,Salesforce 会为所有客户管理 LWC 的配置、部署和升级。

LWC OSS 和平台上的 LWC 有不同的发布时间表。LWC 工程团队通常每周发布一次 LWC OSS,而 Salesforce 平台每年发布三次。由于这种差异,Salesforce 平台上的 LWC 版本比 LWC 的开源版本晚 3-6 个月。

开源 LWC 引擎与 Salesforce 平台上的 LWC 引擎相同。区别在于引擎在编译器级别和运行时的配置方式。

Salesforce 平台上的编译时差异

  • 在 Salesforce 平台上使用实验性 LWC API 受到限制,并引发 linting 错误。
    • 实验性模板 API:lwc:dynamic(已弃用并替换为 <lwc:component lwc:is={componentConstructor}>)
    • 实验性 JavaScript API:、、、、和buildCustomElementConstructorcreateElementswapComponentswapTemplateswapStyle
  • 将 LWC 模块推送到 Salesforce 平台时,将应用以下 linting 规则。
    • 强制执行 @salesforce/eslint-config-lwc/base 中的所有规则。ESLint 忽略这些规则的内联配置。
    • 禁止动态导入 ()。import('c/foo')
    • 禁止从 LWC 模块访问 Aura(例如,)。$A
  • @salesforce/*导入根据组织的元数据(例如,Apex 方法、标签和架构)进行验证。

Salesforce 平台上的运行时差异

  • 组件在启用的情况下运行。此模式允许支持 IE11,IE11 不实现影子 DOM。作为副作用,在页面级别注入的所有样式(例如,using from )都会泄漏到组件中。@lwc/synthetic-shadowloadStylelightning/platformResourceLoader
  • linkSVG 元素上的属性由 Locker 清理,以防止潜在的恶意脚本注入。xlink:href<use>
  • LWC 模块在 Lightning Locker 或 Lightning Web Security 中进行评估。除了应用于标准 Web 平台 API 的限制之外,Locker 和 Lightning Web Security 还为 LWC 组件添加了一些限制:
    • this.template.host总是返回 。null
    • 访问从模板检索到的组件时,始终返回 。shadowRootnull

API 版本控制

从 24 年冬季开始,LWC 支持自定义组件的版本控制。当组件指定版本时,该组件将取决于 Salesforce 版本的版本。组件的每个 HTML、CSS 和 JS 文件对应一个 API 版本。API 版本告诉 LWC 框架的行为与与该组件的 API 版本相对应的 Salesforce 版本的行为相同。

提示

虽然 Salesforce 平台上的 LWC 使用与 LWC 开源相同的代码库,但 Salesforce 平台上的 LWC 版本比开源版本晚 3-6 个月。LWC 开源遵循语义版本控制 (semver) 特征。请参阅 LWC 开源:LWC 版本控制。

升级组件的 API 版本

截至 24 年冬季,58.0 及更早版本的所有 API 版本对应于 58.0(23 年夏季)。如果将 API 版本设置为低于 58.0 的值,则 LWC 默认使用版本 58.0。

若要应用与更高 API 版本相关的 bug 修复和新功能,请升级组件的 API 版本。

注意

API 版本中的警告可能会在下一个 API 版本中成为错误。我们建议您测试每个版本,一次升级一个版本。

要升级组件 API 版本,请执行以下操作:

  1. 发布组件。修复 SFDX 控制台中的任何警告。
  2. 在沙盒中运行组件。修复浏览器 DevTools 控制台中的任何警告。
  3. 将组件的 *.js-meta.xml 文件中的 apiVersion 递增到下一个版本。
  4. 再次发布组件,并验证是否不再看到任何警告。

例如,如果将 apiVersion 值指定为 58.0,则组件的行为将继续与 API 版本 58.0 (Summer ’23) 中的行为相同。

注意

无论如何,自定义组件始终使用最新版本的 Lightning 数据服务和基本 Lightning 组件。apiVersion

组件级中断性变更

组件级重大更改适用于 Lightning Experience 和 Experience Builder 站点的自定义组件。要在组件中实施这些更改,请将 .apiVersion59.0

  • 小写所有 CSS 范围标记
  • 抛出错误而不是 parse5 HTML 错误的警告

组件级功能

在 Winter ’24 中,没有任何与值对应的新 LWC 要素。要查看最新 Salesforce 版本中 LWC 的更改,请参阅发行说明。除非另有说明,否则更改适用于所有值。apiVersionapiVersion

Salesforce 版本和 LWC API 版本

以下是 Salesforce 版本映射到 LWC API 版本的方式。

版本控制注意事项

使用 LWC API 版本控制时,请考虑以下准则。

  • 如果使用的版本早于已知最早的 LWC API 版本,则 LWC 将使用最早的已知版本。例如,如果已知最早的版本是 58.0,而您提供的是 57.0,则 LWC 将使用 58.0。apiVersion
  • 如果最新的 LWC 版本是 60.0,而您提供的是 61.0,则 LWC 将使用 60.0。
  • LWC API 版本控制不适用于 Aura 组件和 LWR。
  • LWC API 版本控制仅适用于 Lightning Experience 中包含该文件的自定义组件。*.js-meta.xml
  • LWR 中的自定义组件在未在 Lightning Experience 或 Experience Cloud 中运行时使用最新的 LWC API 版本。
  • 同一页面上或同一托管包中的组件可以具有不同的 API 版本。

支持的浏览器

Lightning Web 组件支持与 Lightning Experience 相同的浏览器。请参阅 Lightning Experience 支持的浏览器。

Salesforce 于 2023 年 1 月 1 日终止了 Lightning Experience 和 Salesforce Classic 中对 Internet Explorer 11 的支持。在 Winter ’24 之后,您将无法再使用 Internet Explorer 11 和其他旧版浏览器来查看或访问 Lightning Experience。如果您的代码使用了不受支持的浏览器之一,则可以将其删除。我们建议在受支持的浏览器的最新版本中访问 Lightning Experience。

浏览器扩展

虽然有许多第三方浏览器扩展可以个性化和增强您的 Salesforce 体验,但我们建议您查看 AppExchange 以获取来自 Salesforce 合作伙伴的浏览器扩展和应用程序,或查看组件库以获取符合您要求的基本组件。

Salesforce 不提供对第三方浏览器扩展的支持。使用第三方浏览器扩展程序的风险由您自行承担。Salesforce 无法阻止这些扩展程序访问您的 Salesforce 数据,也无法检测到有人试图访问您的数据。

具有 DOM 操作的浏览器扩展

一些第三方浏览器扩展会注入自定义脚本来操作 DOM。出于以下原因,我们不建议也不支持此类第三方浏览器扩展:

  • 操纵 DOM 的浏览器扩展(例如在 DOM 中插入或删除元素)可能会干扰 Lightning Experience 的稳定性并导致意外行为。
  • 不遵循 Salesforce 安全标准的浏览器扩展可能无法在 Lightning Experience 中正常工作。
  • Lightning Experience 的内部 DOM 结构可能会在将来的版本中更改,并且不保证与第三方浏览器扩展的兼容性。

如果您需要使用 DOM,请检查您是否可以通过 lightning/platformResourceLoader 改用 JavaScript 库。

支持的 JavaScript

要开发 Lightning Web 组件,请使用最新版本的 JavaScript。

LWC 支持与 Lightning Experience 相同的浏览器,即 Edge、Chrome、Firefox 和 Safari 的最新稳定版本。要为这些浏览器开发 Lightning Web 组件,您可以使用浏览器支持且 Lightning Locker 允许的任何 JavaScript 功能。

Lightning Locker 提供组件隔离和安全性,允许来自多个来源的代码使用安全、标准的 API 和事件机制执行和交互。若要编写与 Locker 兼容的代码,请使用 Locker 工具。

Lightning Web Security (LWS) 是 Lightning Web 组件的 Lightning Locker 的替代方案。LWS 旨在取代多个版本的 Lightning Locker。有关更多信息,请参阅 Lightning Web 安全。

提示

要学习 JavaScript(或者如果您想复习一下),请从现代 JavaScript 开发 Trailhead 模块开始。

本开发人员指南解释了如何开发 Lightning Web 组件,并记录了特定于 LWC 的 JavaScript 函数,例如用于处理 Salesforce 数据的电线适配器。

本开发人员指南不记录标准 JavaScript,也不教授 JavaScript 基础知识。标准 JavaScript 记录在 Mozilla 开发者网络 (MDN) JavaScript 参考中。如果你正在寻找一个函数的文档,请先尝试 MDN。例如,如果您要查找有关 的信息,请使用 MDN。addEventListener()

注意

Salesforce 于 2023 年 1 月 1 日终止了对 Internet Explorer 11 的支持。在 Winter ’24 之后,您将无法再使用 Internet Explorer 11 和其他旧版浏览器来查看或访问 Lightning Experience。

支持的 Salesforce 目标和工具

Lightning Web 组件支持与许多 Salesforce 目标和工具一起使用。开发组件时,请在组件的配置文件中指定其目标。

  • 闪电体验
  • Salesforce 移动应用程序
  • Lightning 应用程序生成器
  • Experience Builder 网站
  • 体验生成器
  • 独立应用程序
  • 实用栏
  • Lightning Experience 中的快速操作
  • 自定义选项卡
  • Gmail 和 Outlook 集成
  • 嵌入式服务聊天
  • 适用于 Visualforce 的 Lightning 组件
  • 闪电输出(测试版)
  • OmniScripts的
  • 第一代托管软件包
  • 第二代托管软件包
  • 解锁套餐
  • 非托管软件包
  • 更改集

有关更多信息,请参阅在 Salesforce Targets 中使用组件。

不支持将 Lightning Web 组件与这些工具一起使用。要将 Lightning Web 组件与这些工具一起使用,请将该组件包装在 Aura 组件中。

  • Chatter 扩展
  • 全球行动
  • 列表视图操作
  • 相关列表视图操作
  • 标准操作覆盖
  • URL 可寻址选项卡

支持的 Salesforce API

Lightning Web 组件支持与许多 Salesforce API 一起使用。您可以通过导入指定的命名空间模块来访问这些 API。并非列出的 Salesforce API 上的所有功能或端点都受支持。lightningCRM 分析 API

使用 CRM Analytics 数据集和仪表板。目前不支持 Analytics 镜头。请参阅 lightning/analyticsWaveApi 电线适配器和功能。

Einstein 发现 API

检索 Einstein Discovery 故事。目前不支持 Einstein 预测和模型。请参阅 lightning/analyticsSmartDataDiscoveryApi 线路适配器和功能。

EMP API

订阅流媒体频道并收听事件消息。请参阅 lightning/empApi 模块。

元数据 API

从组织部署或检索 Lightning Web 组件包。请参阅 LightningComponentBundle 元数据类型。

移动 SDK

在混合应用中运行 LWC。请参阅 Mobile SDK 开发指南。

Salesforce 控制台 API

使用工作区选项卡和子选项卡。请参阅 Workspace API。尚不支持导航项和实用程序栏 API。

Service Cloud 语音工具包 API

访问服务云语音功能。请参阅《Service Cloud Voice 实施指南》。

工具 API

使用工具 API 处理 Lightning Web 组件包。请参阅 LightningComponentBundle 和 LightningComponentResource 对象。

用户界面 API

使用记录、列表视图等。请参阅 Lightning 数据服务线路适配器和功能。

不支持将 Lightning Web 组件与这些工具一起使用。要将 Lightning Web 组件与这些工具一起使用,请将该组件包装在 Aura 组件中。

  • Lightning 控制台导航项 API
  • Lightning 控制台实用程序栏 API
  • 对话工具包 API
  • Omni 工具包 API

如何选择 Lightning Web 组件或 Aura

Lightning Web 组件比 Aura 组件性能更好,更易于开发。但是,在开发 Lightning Web 组件时,您可能还需要使用 Aura,因为 LWC 尚不支持 Aura 所做的一切。

您如何决定将哪些组件开发为 Lightning Web 组件,哪些组件开发为 Aura 组件?

始终选择 Lightning Web 组件,除非您需要不受支持的功能。

要使用不受支持的体验或功能或使用不受支持的界面,请开发一个 Lightning Web 组件,并将其包装在一个 Aura 组件中,该组件只需访问该体验、功能或界面。

注意

Lightning Web 组件不能包含 Aura 组件。当您开发 Lightning Web 组件时,其 DOM 子树必须完全由 Lightning Web 组件组成。

要使用不能用作 Lightning Web 组件的基本组件,您可能需要在 Aura 中开发所有内容(或几乎所有内容)。

API 生命周期终止政策

Salesforce 承诺自首次发布之日起至少 3 年内支持每个 API 版本。为了完善和提高 API 的质量和性能,超过 3 年的版本可能会被弃用或停用。

Salesforce 会在对该版本的支持结束前至少 1 年通知使用计划弃用的 API 版本的客户。

Lightning Web 组件 (LWC) 已于 19 年春季正式发布,并在 Salesforce API 版本 45.0 及更高版本中受支持。

自定义组件可以使用线路适配器来调用 Salesforce API,例如 Connect REST API 和 UI API。在相应的开发人员指南中查看 API 生命周期终止政策。

如果您请求任何资源或使用已停用的 API 版本中的操作,则 REST API 将返回错误代码。410:GONE

若要识别从旧 API 版本或不受支持的 API 版本发出的请求,请使用免费的 API 总使用量事件类型。

设置开发环境

使用适合您需求的工作流程开发 Lightning Web 组件。我们建议使用 Salesforce DX 工具,但您可能处于不支持这些工具的情况。您仍然可以使用自己喜欢的代码编辑器,并使用自己的工具部署到组织。但是,您无法在开发人员控制台中开发 Lightning Web 组件。

设置编辑器、Linter 和组织

无论您的开发工作流程是什么,您都必须设置代码编辑器、设置 linting 并配置组织才能看到组件的运行情况。

安装代码编辑器

要开发 Lightning Web 组件,请使用您喜欢的代码编辑器。

我们建议使用 Visual Studio Code,因为它的 Salesforce 扩展包提供了用于处理 Salesforce CLI、Lightning 组件框架、Apex 和 Visualforce 的强大功能。

如果您选择使用 Visual Studio Code,请安装它和 Salesforce 扩展包。

  • Visual Studio Code (VS 代码)
  • 适用于 Visual Studio Code 的 Salesforce 扩展包

我们还建议使用 Prettier 进行代码格式设置。VS Code 可以将 Prettier 安装为扩展。对于其他编辑器,请参阅 Prettier 文档。

注意

您无法在 Salesforce 开发人员控制台中开发 Lightning Web 组件。

设置 Linting

Linting 会在编译之前在编辑时发现代码中的错误。Linting 不仅仅是拼写检查,它还引导您远离反模式,转向良好的模式。Salesforce 创建了 ESLint 规则,以最大程度地减少 Lightning Web 组件编程错误。

如果您使用的是 Salesforce DX 项目,则无需手动设置 linting。请参阅在 Scratch 组织中开发 和 在非 Scratch 组织中开发。

如果您使用的不是 Salesforce DX 项目,请从命令行安装 ESLint 规则。有关说明,请参阅 github/salesforce/eslint-plugin-lwc 和 github/salesforce/eslint-config-lwc 存储库。

提示

linting 规则有三个配置级别。查看 eslint-config-lwc 自述文件,并选择符合您编码需求的配置。

如果您正在开发要在 Lightning Web Security 中运行的组件,请参阅安装 Lightning Web Security 的 ESLint 规则。

建立开发组织

注册 Developer Edition 组织。

  • Developer Edition 注册表单

您可以在临时组织和非临时组织中开发 Lightning Web 组件。若要创建临时组织,请将组织配置为开发人员中心。本地开发需要临时组织。

Salesforce CLI 在临时组织中的工作方式与在非临时组织中的工作方式略有不同。我们创建一个项目,并回顾使用 Salesforce DX 工具进行开发中的工作流程。

注意

从 23 年冬季开始,Lightning Web Security 默认在临时组织中启用。有关更多信息,请参阅在临时组织中启用和禁用 LWS。

在开发组织中启用调试模式

要更轻松地调试 JavaScript 代码,请在组织中启用调试模式。启用调试模式时,框架 JavaScript 代码不会缩小,因此更易于阅读和调试。调试模式还为某些警告和错误添加了更详细的输出。

仅对正在积极开发或调试 JavaScript 的用户启用调试模式。对于启用了 Salesforce 的用户来说,Salesforce 速度较慢。

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

使用 Salesforce DX 工具进行开发

我们建议使用 Salesforce DX 工具,以获得最紧密集成的开发体验。此工作流利用 Salesforce CLI、带有 Salesforce 扩展包的 VS Code 编辑器、Salesforce DX 项目以及临时或沙盒组织。

提示

要使用 Salesforce DX 工具设置您的开发人员环境并创建您的第一个组件,请前往 Trailhead 并完成快速入门:Lightning Web 组件项目。

开发移动组件

在开发 Lightning Web 组件时,不仅要检查桌面上的组件演示,还要检查移动设备上的组件演示,这一点很重要。要在虚拟移动设备上预览组件并在编码时查看更改,请使用 Salesforce CLI 移动扩展插件。然后下载并运行 Salesforce 移动应用程序的虚拟设备版本,以预览您的组件如何与 Salesforce 中的其他组件共存。

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

使用您自己的工具进行部署

不使用 Salesforce DX 工具?没关系!使用您自己的工具和元数据 API 部署 Lightning Web 组件。

有时,开发人员和发布管理团队使用不使用 Salesforce DX 工具的部署环境。例如,部署环境可能使用 Eclipse、多个存储库以及 ANT 或 GNU Make 等工具。或者,您的团队可能有一个既定的内部发布流程。虽然我们建议使用我们的工具,但您可以使用元数据以自己的方式部署组件。

要使用软件包和元数据 API 开发和部署 Lightning Web 组件,请按照下列步骤操作。

  1. 创建一个包含组件文件和包 .xml 清单文件的 zip 存档。Lightning Web 组件的元数据 API 类型为 LightningComponentBundle。
  2. 使用 ANT 迁移工具等工具或您自己的工具将组件部署到沙盒或临时组织。

重要

当您使用 Salesforce CLI 时,您可以在项目和目标临时组织之间进行更改跟踪。如果没有这些工具,您必须提出自己的解决方案。像 Github 这样的存储库会监控代码更改。沙盒支持对数据或字段的更改进行审核。

如果您使用的是 Prettier,请考虑添加一个 pre-commit 钩子,以确保您的代码格式正确。

使用 Lightning Web 组件进行开发的最佳实践

要创建安全高效的 Lightning Web 组件,请遵循 Salesforce 开发人员博客上的开发人员最佳实践列表:

  • 通过开发人员最佳实践清单提高一致性并提高开发人员技能
  • Lightning Web 组件性能最佳实践
  • 提高您的 LWC 技能 – 第 1 部分
  • 提高您的 LWC 技能 – 第 2 部分

探索 Trailhead 和示例代码

我们创建了 Trailhead 内容和 GitHub 存储库,以快速启动您的 Lightning Web 组件开发。

Lightning Web 组件配方

Lightning Web 组件的易于理解的代码示例集合。每个配方都演示了如何以尽可能少的代码行编写特定任务,同时遵循最佳实践。“查看源代码”链接会将你直接带到 GitHub 中的代码。

这些方法涵盖了所有基础知识:组合、状态管理、事件、数据访问和导航。《Lightning Web 组件开发人员指南》引用了此存储库中的许多方法。

若要开始,请克隆存储库并按照自述文件中的步骤操作。

Trailhead 项目和模块

在构建 Lightning Web 组件路径上获得创建 Lightning Web 组件的实践经验。

对 Lightning Web 组件进行故障排除,并在 Lightning Web 组件故障排除路径中了解最佳实践。

电动自行车示例应用程序

E-Bikes 示例应用程序演示了如何使用 Lightning Web 组件构建应用程序并与 Salesforce Experience 集成。E-Bikes是一家虚构的电动自行车制造商。该应用程序使用丰富的用户体验帮助电动自行车管理其产品和经销商订单。

安装 E-Bikes 示例应用程序。