代码仍然有改进的空间:
vote 属性或 attribute 被更改,rating 属性可能也会被更改,这会导致 render 被调用两次。尽管重复调用 render 是非常高效的,但浏览器仍然不必要地调用了该函数两次。这就是 LitElement 发挥作用的地方!
LitElement 是 Lit 用于创建快速、轻量级 Web Components 的基类,可在不同框架和环境中使用。接下来,看看 LitElement 能为 <rating-element> 做些什么!
首先从 lit 包中导入并继承 LitElement 基类@customElement 装饰器来替代 customElements.define 调用。
import {LitElement, html, css} from 'lit';import {customElement} from 'lit/decorators.js';
// 记住要继承 LitElementcustomElement('rating-element')export class RatingElement extends LitElement { // 移除 connectedCallback() // 移除文件末尾的 customElements.define // 注释掉 observedAttributes 方法。这会暂时 // 破坏功能,但会在下一步中解决 ... import {LitElement, html, css} from 'lit';
// 记住要继承 LitElementexport class RatingElement extends LitElement { // 移除 connectedCallback() // 暂时注释掉 observedAttributes 方法,这会 // 暂时破坏功能,但我们会在下一步中解决 ... 有哪些变化?
LitElement。LitElement 现在是 <rating-element> 的新基类。html 仍然被导入。css。css 标签函数允许你定义 CSS 标签模板字面量,它在底层支持数学运算、模板等功能。
有关样式的完整功能列表,请参阅 Lit 样式文档。
接下来,将样式从 render 方法移到 Lit 的静态样式表中:
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; } `; ... // 从 render 方法中移除 <style> 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; } `; ... // 从 render 方法中移除 <style> 这是 Lit 中样式的主要存放位置。
在可用的情况下,Lit 会使用浏览器功能,例如可构造样式表,为你的样式提供更快的渲染速度。
接下来,render() 是 LitElement 的生命周期方法,要求我们返回一个 Lit 模板,并且不再需要检查 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>`;} 现在你有了一个带样式的元素!在下一步中,你将使元素响应属性和 attribute 的变化。