Introduction to Lit: A JavaScript Framework

0

Lit is one of the most interesting front-end JavaScript frameworks for reactive programming. It has garnered a lot of interest from developers, but remains relatively under the radar compared to other responsive frameworks. Lit is built on the web components standard and prioritizes speed and a small set of useful features.

Create web components with Lit

There are several ways to start a Lit project. For this tutorial, we’ll use a starter template. You will need a command line with Git and Node.js (npm) installed.

To note: Because it is based on Web Components, Lit uses the Shadow DOM to gain in reactivity.

Go to the command line and type git clone https://github.com/lit/lit-element-starter-js.git. This command deploys a simple sample project into the lit-element-starter-js phone book. cd in this directory and install the dependencies with npm install.

Now you can run the application with npm run serve. If you visit localhost:8000you will see the application running with the screen shown in Figure 1. (Click the button To count button increases the number.)

Screenshot of the Hello World screen. IDG

Figure 1. The Lit startup application

Responsiveness in the Bed frame

Next, let’s look at how Lit is laid out and how it achieves responsiveness.

The main work takes place in /dev/index.htmlas shown in List 1.

Listing 1. Reactivity in Bed


 
   
   <my-element> Demo
   
   
   
   
 
 
   
     

This is child content

  
 

The main thing to note is that the page imports a Polyfill library to ensure that the browser will understand the web components. It also imports a library to make it easier to load web components via npm. Finally, it imports a custom module, my-element.jsfrom the parent directory.

Then take a look at my-element.js in Listing 2, which contains all the fundamental elements of a lit making up.

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`
     

${this.sayHello(this.name)}!

             `;  }  _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 extend the LitElement base class. You might also observe that the styles() and properties() are both static getter methods. We don’t have to worry about signatures; we just use them to define the characteristics of our components.

the styles() The method returns the CSS for the component, and properties() returns the properties. styles() use it css Lit method to define component-scoped CSS in a template literal. properties() exposes the reactive variables of the component: name and count. In each case, the returned object defines the type of variable in the property (for example, name: {type: “String”}).

Property values

Note that properties are given default values ​​in the constructor. These are public properties, so you can comment out the definition of the name, for example, then in /dev/index.htmlassign a value to the name property through its parent, as shown in Listing 3.

List 3. Value of public property


   
     

This is child content

  
 

The List 3 pattern is common among reactive frameworks, allowing unidirectional, downward state flow from parent to child.

Component rendering

The next step is the render method, which returns the markup for the view via the html() method and a template literal. The syntax used in the string literal is tagged literal. Note that this method has full access to the two properties we saw earlier (name and count), as well as the methods defined on the component object, which are defined next.

Built-in and custom methods

Lit has two types of methods: built-in and custom. the _onClick() The method is built-in, which means it has special meaning for the framework. When Lit sees this method, it sets the onclick handler for the given component. In this case, it simply increments the count variable.

The second method is sayHello(name), which is a custom method called from view markup. Note that this method has full access to variables that can be passed as arguments:

${this.sayHello(this.name)}!

All properties and methods are accessible through the this keyword; that is, they are members of the object.

Component registration

Finally, the component asks the browser to register itself as a web component.

As with other reactive frameworks, Lit encourages you to write one-way code, where the model simply reflects state changes without directly modifying the state or the DOM.

Locations and child elements

The Web Components standard uses slits. In our example, you can see that the component itself defines a and the parent passing in a child element (

This is child content

) that will be placed in the slot.

Show and hide items

Lit includes a variety of useful expressions, such as the ability to show and hide items.

For example, if you wanted to display an item when the counter exceeded 5, you could use something like what is shown in Listing 4.

Listing 4. Showing and Hiding Elements

return html`
     

${this.sayHello(this.name)}!

    
Not hidden
             `;

Added functionality in Lit

Now let’s add some functionality to the example. How about displaying collections? Take a look at List 5.

Listing 5. Iterating over an array in Lit

static get properties() {
   return {
     name: {type: String},
     count: {type: Number},
     hobbits: []
   };
 }
 constructor() {
   super();
   this.hobbits = ["Frodo","Sam","Merry","Pippin"];
 }
 render() {
   return html`
     

${this.sayHello(this.name)}!

    
Not hidden
         
           ${this.hobbits.map((color) =>          html`
  • ${color}
  • `        )}     
        `;  }

Listing 5 shows how to add a hobbit property, initialize it with the four most famous hobbits, then cycle through them using a map in the render function. You might notice that React handles this sequence very similarly. You can also extract your looping logic into a function that you call from inside the template, as described here.

To note:Lit also provides a repeat directive, which you can use to efficiently handle list state changes in certain situations.

Make Lit API calls with up to

Now let’s see how to make a remote API call. We will use the Lord of the Rings API to get a list of all known hobbits. You’ll also need to retrieve an authentication token, which is free and quick.

Bed has a until which allows you to display alternative content while waiting for the resolution of a promise. First, add this import to the head of your my-element.js: import {until} from 'lit/directives/until.js';.

Then add the remoteHobbits to the manufacturer: this.remoteHobbits = getRemoteHobbits();.

Third, add the output to the render method like this:

${until(this.remoteHobbits, html`Awaiting remote hobbits...`)}

Notice that here we use until to display a loading message while waiting for the resolution of the promise of remoteHobbits.

Take a look at the definition of promise in getRemoteHobbits()shown in Listing 6.

Listing 6. getRemoteHobbits

const getRemoteHobbits = async () => {
 const response = await fetch("https://the-one-api.dev/v2/character?race=Hobbit",
   {
     "headers": {
       "Authorization":"Bearer "
     }
   }
 );
 const json = await response.json();
 const hobbits = [];
 for (const h of json.docs){
   hobbits.push(html`
  • ${(h.name)}
  • `);  }  return hobbits; }

    Listing 6 uses a normal fetch call to get the list of characters, filtered by race=Hobbit. Note that you must provide your API token in the Authorization on your mind.

    Finally, you gather the JSON response into a set of list items and send it back to insert into the HTML template.

    Now the UI will show the remote API hobbits collection.

    You can find the source for this demo in my GitHub repository.

    Copyright © 2022 IDG Communications, Inc.

    Share.

    About Author

    Comments are closed.