查看原文
其他

Lit 与 React 框架对比指南

小懒 FED实验室 2024-02-12

关注下方公众号,获取更多热点资讯

对于开发人员来说,选择前端框架可能是一个困难的决定,因为有太多的选择。React 是最受欢迎的选择之一,它已经建立了良好的基础,在 2022 年的 JS 状态调查中获得了 83% 的满意度。不过,还有其他一些具有有趣特性和功能的框架值得研究。

如果你有选择困难症,在为下一个项目选择框架时,建议你考虑以下问题:

  • 框架是否具有我所需要的功能?
  • 框架的运行速度如何,是否优于其他框架?
  • 框架的易学易用程度如何?
  • 框架的社区规模如何?

在 2022 年的 JS 状态调查中,Lit 的总体满意度为 70%。Lit 易于学习和使用。

在谷歌的支持下,Lit.js 是现代 JavaScript 框架的快速替代品。它建立在Web Components 之上,只占用极少的模板空间,而这正是困扰现代 JavaScript 框架的问题所在。

Lit.js 由 Google 支持,是现代 JavaScript 框架的快速替代品。它建立在 Web Components 之上,只占用极少的模板空间,而这正是困扰现代 JavaScript 框架的问题所在。

本文首先对 Lit 做一个基本的介绍,从语法、模版、组件、hook、生命周期等方面与 React 做一个对比,最后讨论在下一个项目中是否要选择 Lit。

  • Lit 基本介绍
  • Lit 与 React 全方位对比
  • 如何选择?

1.Lit 基本介绍

Lit 是 Google 提供的一组开源库,可帮助开发者构建快速、轻量且适用于任何框架的组件。借助 Lit,您可以构建可共享的组件、应用、设计系统等。

Lit 不同于其他前端框架的特点:

  • LitElement 基类是对原生 HTMLElement 方便而通用的扩展。该类可扩展用于定义自己的组件
  • 富有表现力且声明式的模板使得定义组件的渲染方式变得容易。
  • 响应式属性是 Lit 组件的内部状态。当响应式属性发生变化时,组件会自动重新渲染。
  • 作用域样式有助于保持CSS选择器的简单性,确保组件样式不会影响其他上下文。
  • 支持原生 JavaScript、TypeScript 和人性化(装饰器和类型声明)

刚刚 Lit 团队发布了最新一个大版本 Lit 3.0,带来了一些重大变化:

  • 不再支持 IE11。
  • Lit的 npm 模块现已发布为 ES2021。
  • 删除了 Lit 2.0 版本中废弃的 API。
  • SSR hydration支持模块已移至 @lit-labs/ssr-client 包。
  • 在TypeScript 实验性装饰器和标准装饰器之间统一装饰器行为。
  • 不再支持 Babel 装饰器 "2018-09" 版本

更多信息详见:前端快讯|Lit 3.0 已发布,再见 IE,你好 TC39 装饰器!

2.Lit 与 React 对比

Lit 的核心概念和功能在很多方面与 React 类似,React自2013年以来一直存在,并且比Lit更为流行,Lit 也与其存在一些重要的区别和差异:

2.1.包的体积

Lit 非常小:经缩减大小和 gzip 压缩后可减至 5kb 左右,而 React + ReactDOM 的大小超过 40kb。

2.2.渲染性能

在对 Lit 的模板系统 lit-html 与 React 的 VDOM 进行对比的公开基准测试中,lit-html 在最糟糕的情况下比 React 快 8-10%,在比较常见的用例中快 50% 以上。

LitElement(Lit 的组件基类)给 lit-html 增加的开销极低,但在内存用量、交互时间和启动用时等组件特性的对比中却比 React 的性能高 16-30%。

2.3.编译构建

借助新的浏览器功能(例如 ES 模块和带标记模板字面量),Lit 不需要编译即可运行。也就是说,您可以使用脚本标记、浏览器和服务器设置开发环境,然后 Lit 便可正常运行。

借助 ES 模块以及 Skypack 或 UNPKG 等现代 CDN,您甚至有可能无需 NPM 即可开始使用 Lit!

不过,如果您愿意,您仍可构建并优化 Lit 代码,Lit 就是常规 JavaScript,不需要框架专用的 CLI,也不需要构建处理。

2.4.与框架无关

Lit 的组件以一组名为 Web Components 的网页标准为基础构建。这意味着,在 Lit 中构建组件可确保在当前和未来的框架中都能正常工作。如果它支持 HTML 元素,那么它就支持 Web Components。

框架互操作性方面的唯一问题是有些框架对 DOM 的支持有限制。React 就是其中一种框架,不过它通过引用提供了解决办法,但 React 中的引用并不是让人愉快的开发者体验。

Lit 3.0 发布的 @lit/react 的项目,它会自动解析您的 Lit 组件并生成 React 封装容器,让您无需使用引用。

2.5.TypeScript 支持

虽然您可以使用 JavaScript 编写所有 Lit 代码,但 Lit 是使用 TypeScript 编写的,而且 Lit 团队也建议开发者使用 TypeScript!

Lit 团队一直与 Lit 社区合作来帮助维护项目,即使用 lit-analyzerlit-plugin 在开发中和构建时实现 TypeScript 类型检查和 Lit 模板智能感知。

2.6.开发者工具内置

Lit 组件就是 DOM 中的 HTML 元素。这意味着,即使为了检查组件,您也不需要为浏览器安装任何工具或扩展程序。只需打开 DevTools,选择某个元素,然后浏览其属性或状态即可。

2.7.投入产出比

使用 Lit 不需要大量的投入!您可以在 Lit 中构建组件并将其添加到现有项目中。如果不喜欢这些组件,那么您不必立刻转换整个应用,因为网页组件可在其他框架中工作!

2.8.功能特性

1)JSX 和模板

JSX 是 JavaScript 的语法扩展,其功能类似于模板语言,但具有 JavaScript 的全部功能。React 用户可以使用 JSX 在 JavaScript 代码中轻松编写模板。Lit 模板的作用与此类似,只是将组件 UI 表述为其状态的函数。

下面是 React 中的 JSX 模板示例:

import 'react';
import ReactDOM from 'react-dom';

const name = 'World';
const el = (
  <>
    <h1>Hello, {name}</h1>
    <div>How are you? </div>
  </>

);
ReactDOM.render(
  el,
  mountNode
);

下面是 Lit 中的 JSX 模板示例:

import {html, render} from 'lit';

const name = 'World';
const el = html`
  <h1>Hello, 
${name}</h1>
  <div>How are you?</div>`
;

render(
  el,
  mountNode
);

正如我们在上述示例中看到的,Lit 不需要 React 片段来在其模板中组合多个元素。相反,Lit 模板使用 HTML 标记的模板字面进行包装。

2)组件和属性

组件是自包含的、可重用的代码片段。它们执行的操作与 JavaScript 函数相同,但它们可以独立工作并返回 HTML。React 组件分为两种类型:类组件和函数组件。

类组件:

Lit 组件的等效物是 LitElement,它是一种基于 Lit HTML 模板编写组件的绝佳方式。LitElement 遵循面向对象编程(OOP)范例,并提供一个基类,帮助您管理其属性和各种属性API。

函数组件:

Lit 不使用 JSX,所以没有与 React 函数组件一一对应的对应关系。但是,可以更简单地编写一个接受属性并根据这些属性渲染 DOM 的函数。

下面是一个 React 函数组件的示例:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const el = <Welcome name="World"/>
ReactDOM.render(
  el,
  mountNode
);

下面是一个 Lit 函数组件的示例:

import {html, render} from 'lit';

function Welcome(props) {
  return html`<h1>Hello, ${props.name}</h1>`;
}

render(
  Welcome({name'World}),
  document.body.querySelector('
#root')
);

3)状态和生命周期

state 是一个包含组件数据或信息的 React 对象。组件的状态可以随时间变化。每当状态改变时,组件重新渲染。

Lit 的响应性属性是 React 状态和属性的结合体。当发生变化时,响应性属性可以触发组件生命周期,重新渲染组件,并可以选择性地读取或写入属性。响应性属性有两种变体:

  • 公共响应性属性
  • 内部响应状态

React中的响应性属性实现如下:

import React from 'react';

class MyEl extends React.Component {
  constructor(props) {
    super(props)
    this.state = {name'there'}
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.name !== nextProps.name) {
      this.setState({name: nextProps.name})
    }
  }
}

Lit 的响应式属性示例如下:

import {LitElement} from 'lit';
import {property} from 'lit/decorators.js';

class MyEl extends LitElement {
  @property() name = 'there';
}

内部响应状态指的是不暴露给组件公共 API 的响应式属性。这些状态属性缺乏相应的属性,并且不打算在组件外部使用。组件的内部响应状态应该由组件自身确定。

React 和 Lit 有相似的生命周期,但也有一些小而显著的差异。让我们更仔细地看一些这些框架共同拥有的方法。

a)constructor

// React
import React from 'react';
import Chart from 'chart.js';

class MyEl extends React.Component {
  constructor(props) {
    super(props);
    this.state = { counter0 };
    this._privateProp = 'private';
  }
}

// Lit
class MyEl extends LitElement {
  static get properties() {
    return { counter: {typeNumber} }
  }
  constructor() {
    this.counter = 0;
    this._privateProp = 'private';
  }
}

b)render

// React
render() {
  return <div>Hello World</div>
}

// Lit
render() {
  return html`<div>Hello World</div>`;
}

c)componentDidMount vs firstUpdated and connectedCallback

// React
componentDidMount() {
  this._chart = new Chart(this.chartElRef.current, {...});
}

componentDidMount() {
  this.window.addEventListener('resize'this.boundOnResize);
}

// Lit
firstUpdated() {
  this._chart = new Chart(this.chartEl, {...});
}

connectedCallback() {
  super.connectedCallback();
  this.window.addEventListener('resize'this.boundOnResize);
}

d)componentWillUnmount vs disconnectedCallback

// React
componentWillUnmount() {
  this.window.removeEventListener('resize'this.boundOnResize);
}

// Lit
disconnectedCallback() {
  super.disconnectedCallback();
  this.window.removeEventListener('resize'this.boundOnResize);
}

4)React Hooks vs LitElement

Hooks 是一种允许 React 函数组件 “连接到” React 状态和生命周期特性的函数。Hooks 不能在类中使用,但是它们允许我们在不使用类的情况下使用React。

与 React 不同,Lit 不提供一种从函数创建自定义元素的方式,但是 LitElement 通过以下方式解决了大多数与React类组件的主要问题:

  • 在构造函数中不接受参数
  • 自动绑定所有@event绑定(通常是到自定义元素的引用)
  • 将类属性实例化为类成员

下面是Hooks在React中的示例(在创建Hooks时的时间点上):

import React from 'react';
import ReactDOM from 'react-dom';

class MyEl extends React.Component {
  constructor(props) {
    super(props); // Leaky implementation
    this.state = {count0};
    this._chart = null// Deemed messy
  }

  render() {
    return (
      <>
        <div>Num times clicked {count}</div>
        <button onClick={this.clickCallback}>click me</button>
      </>

    );
  }

  clickCallback() {
    // Errors because `this` no longer refers to the component
    this.setState({countthis.count + 1});
  }
}

实现相同的,使用 LitElement:

class MyEl extends LitElement {
  @property({typeNumber}) count = 0// No need for constructor to set state
  private _chart = null// Public class fields introduced to JS in 2019

  render() {
    return html
        <div>Num times clicked ${count}</div>
        <button @click=${this.clickCallback}>click me</
button>`;
  }

  private clickCallback() {
    // No error because `
this` refers to component
    this.count++;
  }
}

5)React 和 Lit 中的 Ref

Refs 是 React 函数,它允许我们访问 DOM 元素和我们创建的任何 React 元素。当我们想在不使用道具的情况下更改子组件的值时,就会用到它们。

在 Lit 中,使用 @query 和 @queryAll 装饰器创建 refs。这些装饰器几乎分别等同于 querySelector 和 querySelectorAll,并直接呈现到 DOM。

// React
const RefsExample = (props) => {
 const inputRef = React.useRef(null);
 const onButtonClick = React.useCallback(() => {
   inputRef.current?.focus();
 }, [inputRef]);

 return (
   <div>
     <input type={"text"} ref={inputRef} />
     <br />
     <button onClick={onButtonClick}>
       Click to focus on the input above!
     </button>
   </div>

 );
};


// Lit: 使用 @query 装饰器
@customElement("my-element")
export class MyElement extends LitElement {
  @query('input'// Define the query
  inputEl!: HTMLInputElement; // Declare the prop

  // Declare the click event listener
  onButtonClick() {
    // Use the query to focus
    this.inputEl.focus();
  }

  render() {
    return html
      <input type="text">
      <br />
      <!-- Bind the click listener -->
      <button @click=${this.onButtonClick}>
        Click to focus on the input above!
      </button>

   ;
  }
}

3.如何选择?

每个框架都有其独特的优点和缺点。React支撑着许多大公司的网络应用,如Facebook、Twitter和Airbnb。它还拥有庞大的开发者和贡献者社区。

如果你目前正在使用 React 并对此选择感到满意,那么我认为您没有任何理由改用其他框架。但是,如果您正在开发的项目需要非常快的性能,那么您可以考虑使用 Lit。

如果你在公司内部项目有实践的机会,建议你试试 Lit,也许你会慢慢喜欢上它😍!

继续滑动看下一个

Lit 与 React 框架对比指南

小懒 FED实验室
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存