天天看点

Lit 2.x:会让 Web Component 真正火起来么?

作者:高级前端进阶

大家好,很高兴又见面了,我是"高级前端‬进阶‬",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力。

Lit 2.x:会让 Web Component 真正火起来么?

今天给大家带来的主题是Lit ,即一个简单的库,用于构建快速、轻量级的 Web Component。话不多说,直接进入正题!

1.什么是 Lit

Lit 是一个简单的库,用于构建快速、轻量级的 Web Component。 Lit 的核心是一个消除样板的组件基类,它提供反应式状态、作用域样式和一个微小、快速且富有表现力的声明性模板系统。

Lit 2.x:会让 Web Component 真正火起来么?

Lit 具有以下优势:

  • 简单/去样板化:Lit 建立在 Web Component 标准之上,添加了反应性、声明性模板和一些优秀功能,以减少样板文件并使工作更轻松。 每个 Lit 功能都经过精心设计,并考虑到 Web 平台的发展。
  • 快速地/体积小/即时更新:Lit 的体积约为 5 KB(minified and compressed),有助于保持较小的包体积并缩短加载时间。而且渲染速度非常快,因为 Lit 在更新时只涉及 UI 的动态部分 ,无需重建虚拟树并将其与 DOM 进行比较。
  • 可互操作/面向未来:每个 Lit 组件都是原生 Web Component,具有超强的互操作性。 Web Component 可以在任何使用 HTML 的地方工作,可以使用任何框架,也可以不使用框架。 这使得 Lit 成为构建可共享组件、设计系统或可维护、面向未来的网站和应用程序的理想选择。

除了以上特点外,Lit 的优势还包括:

  • 标准自定义元素:Lit 组件是标准的自定义元素,因此浏览器将它们完全视为内置元素。 在手写的 HTML 或框架代码中使用它们,从 CMS 或静态站点构建器输出它们,甚至在 JavaScript 中创建实例
  • 支持范围样式(Scoped styles):Lit 默认使用 Shadow DOM 来确定样式的范围,从而使得 CSS 选择器保持简单,并确保组件的样式不会影响页面上的任何其他样式,也不受其影响。
  • 支持反应性:支持声明响应式属性来对组件的 API 和内部状态进行建模。 每当反应性属性(或相应的 HTML 属性)发生变化时,Lit 组件就会有效地重新渲染。
  • 声明性模板:Lit 模板基于标记的模板文字,简单、富有表现力且快速,具有 HTML 标记和内联的原生 JavaScript 表达式。 无需学习自定义语法,更重要的是无需编译。

目前 Lit 在 Github 上通过 BSD-3-Clause 协议开源,有超过 15.1k 的 star、0.8k 的 fork、38.1k 的项目依赖量,代码贡献者 160+,npm 周平均下载量 845k,是一个妥妥的前端优质开源项目,值得长期关注。

2.Lit 的使用场景

开发者可以使用 Lit 构建几乎任何类型的 Web UI!

每个 Lit 组件都是标准的 Web 组件。 Web 组件具有互操作性的超强能力,本身受浏览器的支持,可以在任何 HTML 环境中使用,可以使用任何框架,也可以不依赖框架。

Lit 2.x:会让 Web Component 真正火起来么?

这使得 Lit 成为开发可共享组件或设计系统的理想选择。 Lit 组件可以跨多个应用程序和站点使用,即使这些应用程序和站点构建在各种前端堆栈上。 使用 Lit 组件的站点开发人员不需要编写甚至不需要查看任何 Lit 代码,可以像使用内置 HTML 元素一样使用这些组件。

Lit 还非常适合用于逐步增强基本 HTML 网站。 浏览器将识别标记中的 Lit 组件并自动初始化, 无论站点是手工制作的、通过 CMS 管理的、使用服务器端框架构建的,还是由 Jekyll 或 Eleventy 等工具生成的。

当然,开发者也可以使用 Lit 组件构建高度交互、功能丰富的应用程序,就像使用 React 或 Vue 等框架一样。 Lit 的功能和开发人员体验与这些流行的替代方案相当,但 Lit 通过采用浏览器的本机组件模型最大限度地减少锁定、最大限度地提高灵活性并提高可维护性。

总结起来,Lit 非常适用于以下场景:

  • 共享组件:支持可放入任何站点、构建在任何堆栈上的交互式内容。由于浏览器本身就支持 Web Component,因此 Web Component 是完美的解决方案,而且 Lit 使它们易于构建。
  • 设计系统:设计系统可帮助创造始终如一的卓越品牌体验,而 Lit 能够有效解决跨框前端架、跨团队的诸多问题。
  • 网站和应用程序:使用 Lit 组件逐步增强静态站点或构建整个应用程序。 通过采用 Web Component,Lit 最大限度减少了锁定并提高了可维护性。

3.开始使用 Lit

3.1 安装 Lit

首先需要使用 npm 安装 Lit:

npm i lit           

然后导入 JavaScript 或 TypeScript 文件:

import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators.js";           

当然,Lit 还可以作为预构建的单文件包提供,从而提高开发工作流程的灵活性:例如,如果开发者更愿意下载单个文件而不是使用 npm 和构建工具。

这些包是没有依赖关系的标准 JavaScript 模块 , 任何现代浏览器都能够从 <script type="module"> 中导入并运行这些代码,如下所示:

import {
  LitElement,
  html,
} from "https://cdn.jsdelivr.net/gh/lit/dist@2/core/lit-core.min.js";           

3.2 使用 Lit 开发一个 Web Component

下面使用 Lit 开发了一个 Web Component:

import {LitElement, html, css} from 'lit';
import {customElement, property, state} from 'lit/decorators.js';
import {play, pause, replay} from './icons.js';
@customElement("my-timer")
// @customElement是类装饰器工厂将装饰类定义为自定义元素,即 my-timer
export class MyTimer extends LitElement {
  static styles = css`/* playground-fold */
  :host {
    display: inline-block;
    min-width: 4em;
    text-align: center;
    padding: 0.2em;
    margin: 0.2em 0.1em;
  }
  footer {
    user-select: none;
    font-size: 0.6em;
  }
  @property() duration = 60;
  @state() private end: number | null = null;
  @state() private remaining = 0;
  render() {
    const {remaining, running} = this;
    const min = Math.floor(remaining / 60000);
    const sec = pad(min, Math.floor(remaining / 1000 % 60));
    const hun = pad(true, Math.floor(remaining % 1000 / 10));
    return html`
      ${min ? `${min}:${sec}` : `${sec}.${hun}`}
      <footer>
        ${remaining === 0 ? '' : running ?
          html`<span @click=${this.pause}>${pause}</span>` :
          html`<span @click=${this.start}>${play}</span>`}
        <span @click=${this.reset}>${replay}</span>
      </footer>
    `;
  }
  start() {
    this.end = Date.now() + this.remaining;
    this.tick();
  }
  pause() {
    this.end = null;
  }
  reset() {
    const running = this.running;
    this.remaining = this.duration * 1000;
    this.end = running ? Date.now() + this.remaining : null;
  }
  tick() {
    if (this.running) {
      this.remaining = Math.max(0, this.end! - Date.now());
      requestAnimationFrame(() => this.tick());
    }
  }
  get running() {
    return this.end && this.remaining;
  }
  connectedCallback() {
    super.connectedCallback();
    this.reset();
  }
}           

上面代码有几点值得说明:

  • Lit 的主要功能是 LitElement 基类,它是原生 HTMLElement 的便捷且多功能的扩展, 主要功能是:管理元素 properties 和 attribute 并渲染 lit-html 模板的基本元素类。
  • @property()是一个属性装饰器,它创建相应属性值的反应性属性。 当设置装饰属性时,元素将更新并渲染。 也可以选择提供 PropertyDeclaration 来配置属性功能。
  • @state() 声明一个私有或受保护的响应式属性,代表组件的公共 API 和/或内部状态,该属性在更改时会触发元素的更新,它不会从相应的属性中反映出来。
  • 默认情况下,样式是有范围(scope)的,使 CSS 选择器保持简单,并确保组件的样式不会污染(或被污染)周围的上下文。
  • Lit 富有表现力的声明性模板(利用 JavaScript 标记模板文字)可以轻松描述组件的渲染方式。
  • Lit 在普通 JavaScript 表现良好,开发者可以通过使用装饰器和类型声明来使用 TypeScript 以获得更好的人体工程学效果。

声明了 my-timer 这个 Web Component 后,接着就可以在 HTML 中引入这个 my-timer 来直接使用:

<!doctype html>
<head>
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@1,800&display=swap" rel="stylesheet">
  <script type="module" src="./my-timer.js"></script>
  <style>
    body {
      font-family: 'JetBrains Mono', monospace;
      font-size: 36px;
    }
  </style>
</head>
<body>
  <my-timer duration="7"></my-timer>
  <my-timer duration="60"></my-timer>
  <my-timer duration="300"></my-timer>
</body>           

当然,Lit 还包括:指令(Directives)、Shadow DOM、生命周期(Lifecycle)、上下文(Context)、Lit 服务端渲染(Lit SSR)、前端框架集成等高级用法,这些可以在文末的参考资料中直接使用,本文不再过多展开。

4.本文总结

本文主要和大家介绍 Lit ,即一个简单的库,用于构建快速、轻量级的 Web Component。相信通过本文的阅读,大家对 Lit 会有一个初步的了解。

因为篇幅有限,关于 Lit 的更多用法和特性文章并没有过多展开,如果有兴趣,可以在我的主页继续阅读,同时文末的参考资料提供了大量优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏,您的支持是我不断创作的动力。

参考资料

https://github.com/lit/lit

https://lit.dev/tutorials/intro-to-lit/

https://lit.dev/docs/

https://www.npmjs.com/package/lit

https://lit.dev/docs/frameworks/react/

https://coderpad.io/blog/development/web-components-101-framework-comparison/

https://medium.com/front-end-weekly/web-components-lwc-stencil-and-lit-by-numbers-b158efcf82f7

继续阅读