Base Component Composition

As modular building blocks, base components follow several structures: composition or flat structure. Understanding the differences can be helpful as you work with base components or build your own custom components.

Many base components can compose other base components. We sometimes refer to this relationship as parent and child components. A common pattern for working with base components is to compose them declaratively like this.

Here are some examples of base components that compose other base components.

ParentChildDescription
lightning-accordionlightning-accordion-sectionDisplays content in sections that can be expanded and collapsed
lightning-breadcrumbslightning-breadcrumbDisplays a hierarchy path of the page you're visiting
lightning-button-grouplightning-buttonDisplays a group of buttons
lightning-button-menulightning-menu-itemDisplays a dropdown menu with a list of action items
lightning-layoutlightning-layout-itemDisplays content in a responsive grid system
lightning-progress-indicatorlightning-progress-stepDisplays an indication on the progress of a process
lightning-record-edit-formlightning-input-fieldDisplays a form for record editing
lightning-record-view-formlightning-output-fieldDisplays record data
lightning-tabsetlightning-tabDisplays content in sections that can be shown one at a time
lightning-vertical-navigationlightning-vertical-navigation-sectionDisplays a list of links for navigation

Base component composition is made possible by using slots in the parent components. For more information, see Pass Markup to a Base Component Slot.

You can create multiple instances of the nested base component via data from a JavaScript object. For example, if you have a large list to iterate through, you can use the for:each directive to display a list of menu items on the lightning-button-menu component.

In the component's JavaScript file, pass in the label and value pairs to lightning-menu-item.

Some base components, such as lightning-combobox and lightning-select, render child components internally. This presents a flatter component surface for you to work with.

In this lightning-select example, you can use a getter to pass in the options. The component takes care of rendering the <select> and <option> tags.

When you compare composition and flat structures, the latter uses an attribute like options for you to pass in your configuration information.

Here are some examples of base components that use a flat structure.

Base ComponentUsage
lightning-checkbox-groupPass in the label and value that describe checkbox options to the options attribute.
lightning-comboboxPass in the label and value that describe a menu item to the options attribute.
lightning-dual-listboxPass in the label and value that describe a menu item to the options attribute.
lightning-datatablePass in the label, fieldName, and type to the columns attribute. Pass in column data to the data attribute.
lightning-mapPass in the map markers to the map-markers attribute.
lightning-pill-containerPass in the pill items to the items attribute.
lightning-radio-groupPass in the label and value that describe radio options to the options attribute.
lightning-selectPass in the label and value that describe an option to the options attribute.
lightning-treePass in the tree items to the items attribute.

The flatter structure in a base component is made possible by using an attribute to pass in configuration information and data. For more information, see Pass Configuration and Data to a Base Component.

As you build with base components and create your own components, it's helpful to understand the use cases for composition vs flat structures.

  • Consider composition for general use cases, such as when you want to break down complexity of code and logic
  • Consider a flat structure when you render large numbers of elements through composed components

If you end up with a heavily composed structure, consider moving the logic from child components back to a parent component. Doing so allows your parent component to inline as many of the elements, which improves performance by avoiding the rendering of more custom components where possible.

Keep in mind that the number of elements, functions, and event handlers increase component size and has performance implications especially when you are working with large numbers of such components on a page. If possible, move expensive operations higher up the component tree and reduce the number of operations a leaf component handles.

Additionally, consider these performance guidelines.

  • Avoid or consolidate unnecessary DOM elements and event handlers.
  • Reduce unnecessary rendering and rerendering.

For frequently reused components, expensive operations impact performance exponentially. Here are several ways to reduce performance overhead.

  • Avoid making deep copies of large objects.
  • Avoid processing collections of records or other data.
  • Avoid forced rerendering and other DOM manipulations.