Listing 1. Reactivity in Lit
<html>
<head>
<meta charset="utf-8" />
<title><my-element> Demo</title>
<script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script src="../node_modules/lit/polyfill-support.js"></script>
<script type="module" src="../my-element.js"></script>
<style>
p {
border: solid 1px blue;
padding: 8px;
}
</style>
</head>
<body>
<my-element>
<p>This is child content</p>
</my-element>
</body>
</html>
The main thing to note is that the page imports a Polyfill library to ensure the browser will understand Web Components. It also imports a library to assist with loading Web Components via npm. Finally, it imports a custom module, my-element.js, from the parent directory.
Next, take a look at my-element.js in Listing 2, which contains all the fundamental elements of a lit component
Listing 2. Elements of a Lit-based component
import {LitElement, html, css} from 'lit';
/**
* An example element.
*
* @fires count-changed - Indicates when the count changes
* @slot - This element has a slot
* @csspart button - The button
*/
export class MyElement extends LitElement {
static get styles() {
return css`
:host {
display: block;
border: solid 1px gray;
padding: 16px;
max-width: 800px;
}
`;
}
static get properties() {
return {
/**
* The name to say "Hello" to.
* @type {string}
*/
name: {type: String},
/**
* The number of times the button has been clicked.
* @type {number}
*/
count: {type: Number},
};
}
constructor() {
super();
this.name = 'World';
this.count = 0;
}
render() {
return html`
<h1>${this.sayHello(this.name)}!</h1>
<button @click=${this._onClick} part="button">
Click Count: ${this.count}
</button>
<slot></slot>
`;
}
_onClick() {
this.count++;
this.dispatchEvent(new CustomEvent('count-changed'));
}
/**
* Formats a greeting
* @param name {string} The name to say "Hello" to
* @returns {string} A greeting directed at `name`
*/
sayHello(name) {
return `Hello, ${name}`;
}
}
window.customElements.define('my-element', MyElement);
The first thing to note is that lit extends the LitElement base class. You might also observe that the styles() and properties() methods are both static getter methods. We don’t have to worry about the signatures; we just use them to define the characteristics of our components.
The styles() method returns the CSS for the component, and properties() returns the properties. styles() uses the css method from Lit to define component-scoped CSS in a template literal. properties() exposes the component’s reactive variables: name and count. In each case, the object returned defines the variable type in the property (for example, name: {type: “String”}).
Listing 3. Public property value
<body>
<my-element name="Galadriel">
<p>This is child content</p>
</my-element>
</body>