Skip to content

Update code reuse overview. Fixes #83. #144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 1, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions packages/lit-dev-content/site/guide/composition/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,34 @@ eleventyNavigation:
order: 1
---

<div class="alert alert-warning">
There are several strategies you can use to make your Lit code reusable:

TODO: Write this section. Rough notes follow.
* Composition
* Directives
* Reactive controllers
* Class mixins
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest linking these to their respective sections

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linked from the discussion below, instead. From here, it would be unclear to me whether I was linking down on the page or to a separate page.


</div>
_Composition_ is the process of assembling complex components from simpler components. A component can use subcomponents in its template. Components can use standard DOM mechanisms to communicate: setting properties on subcomponents, and listening for events from subcomponents.

TL;DR: There are several strategies you can use to factor Lit code into reusable modules.
Although component composition is the default way to think about breaking a complex Lit project down into smaller units, there are three other notable code patterns useful for factoring your Lit code:

* Directives are special functions that customize how an expression is processed and rendered.
* Class mixins are factory functions that add a specific set up functionality to a base class.
* Lit Reactive controllers are objects that can hook into a host component's update lifecycle.
[_Directives_](/guide/composition/directives/) are functions that can customize how Lit renders values. Unlike a simple function in a template expression, a directive can hold state between render cycles, and directly manipulate the generated DOM.

[_Reactive controllers_](/guide/composition/controllers/) are objects that can hook into the update lifecycle of a Lit component, encapsulating state and behavior related to a feature into a separate unit of code.

[_Class mixins_](/guide/composition/mixins/) let you write reusable partial component definitions and "mix them in" to a component's inheritance chain.

Directives are useful for code that needs to customize rendering in some fashion; while they have some similarities to components, it's best to think of these as rendering helpers, and not a full-fledged component model. On the other hand, both mixins and reactive controllers let you factor component logic related to a given feature into a reusable unit. See the next section for a comparison of controllers and mixins.

## Controllers and mixins

The primary difference between controllers and mixins is their relationship with the the component. A component has a "has-a" relationship with a reactive controller, since it owns the controller. A component has an "is-a" relationship with a mixin, since the component inherits its behavior.

A reactive controller is a separate object owned by a component. The controller can access methods and fields on the component, and the component can access methods and fields on the controller. But the controller can't (easily) be accessed by someone using the component, unless the component exposes a public API to it. The controller's lifecycle methods are called _before_ the corresponding lifecycle method on the component.

A mixin, on the other hand, becomes part of the component's prototype chain. Any public fields or methods defined by the mixin are part of the component's API. And because a mixin is part of the prototype chain, your component has some control of when the mixin's lifecycle callbacks are called.

In general, if you're trying to decide whether to package a feature as a controller or a mixin, you should choose a controller _unless_ the feature requires one of the following:

* Adding public API to the component.
* Very granular access to the component lifecycle.