组件

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

注意

允许继承,但不建议这样做,因为组合通常更有效。若要在组件之间共享逻辑,请使用仅包含逻辑的模块。请参阅其他 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 组件行。
  • 若要查看其中一个依赖项的详细信息,请单击“名称”列中的链接。
查看组件依赖关系树

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