There are still ways the code can be improved:
vote
property or attribute is changed, the rating
property may also be changed which will result in calling render
twice. Despite repeat calls of render
being a very efficient, the browser is still needlessly calling that function twice.This is where LitElement
comes in!
LitElement
is Lit's base class for creating fast, lightweight web components that can be used across frameworks and environments. Next, take a look at what LitElement
can do for the <rating-element>
!
Start by importing and subclassing the LitElement
base class from the lit
package@customElement
decorator to replace the customElements.define
call.
import {LitElement, html, css} from 'lit';
import {customElement} from 'lit/decorators.js';
// Remember to extend LitElement
@customElement('rating-element')
export class RatingElement extends LitElement {
// remove connectedCallback()
// remove customElements.define at the end of the file
// comment out the observedAttributes method. this will break
// functionality for now, but it'll be addressed in the next step
...
import {LitElement, html, css} from 'lit';
// Remember to extend LitElement
export class RatingElement extends LitElement {
// remove connectedCallback()
// comment out the observedAttributes method for now this will break
// functionality for now, but we'll tackle that in the next step
...
What's changed?
LitElement
is imported.LitElement
is now the new base class for <rating-element>
.html
is still imported.css
is imported.The css
tag function allows you to define CSS tagged template literals, which enable math, templating, and other features under the hood.
For a comprehensive list of styling features, refer to the Lit Styles documentation.
Next, move the styles from the render method to Lit's static stylesheet:
export class RatingElement extends LitElement {
static styles = css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
`;
...
// remove <style> from render method
export class RatingElement extends LitElement {
static styles = css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
`;
...
// remove <style> from render method
This is where most styles live in Lit.
Where available, Lit uses browser features such as Constructable Stylesheets to provide faster rendering times for your styles.
Next, render()
is a LitElement
lifecycle method which requires us to return a Lit template and no longer needs to check for the shadow root:
render() {
return html`
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
}
render() {
return html`
<button
class="thumb_down"
@click=${() => {
this.vote = 'down';
}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button
class="thumb_up"
@click=${() => {
this.vote = 'up';
}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
}
Now you have a styled element! In the next step you will make the element react to property and attribute changes.