从构建开始的Lit开发

如果对Lit还没有基础的了解可以看我上篇文章看完本篇,教你用Lit实现简单组件开发 - 掘金 实际上使用基础JS开发Lit还是有些过于繁琐,同时我认为装饰器是Lit的重要组成部分,所以本篇将会为您介绍基于babel装饰器的Lit开发

构建

首先看到这里我将会默认您对Lit已经有了基础的了解了,所以我将不会对Lit的基础语法有过多的介绍。 总所周知,原生JS是不支持装饰器的语法的,目前JS装饰器语法还在提案中,所以我们需要在打包的过程中使我们装饰器的代码编译为原生JS代码。这就需要用到babel

@babel/plugin-proposal-decorators从版本 7.23 开始,Babel通过插件支持标准装饰器。 Babel 不支持 TypeScript 实验性装饰器,因此您必须使用具有标准装饰器语法accessor的 Lit 装饰器,并在装饰类字段上使用关键字。

javaScript 复制代码
// babel.config.json
{
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"version": "2023-05"}]
  ]
}
注意:、Lit装饰器仅适用于"version": "2023-05"."2018-09"不支持其他版本,包括以前支持的版本。

如果你使用TypeScript来进行开发的话,TS是支持装饰器语法的不需要做额外的编译

所以接下来我们使用Vite来打包构建项目

javaScript 复制代码
//vite.config.js
import { defineConfig } from "vite";
import babel from "vite-plugin-babel";
import litCss from "vite-plugin-lit-css";
​
export default defineConfig({
  build: {
    outDir: "./dist",
  },
  plugins: [
    litCss(),
    babel({
      babelConfig: {
        babelrc: false,
        configFile: false,
        plugins: [
          ["@babel/plugin-proposal-decorators", { version: "2023-05" }],
          "@babel/plugin-transform-class-static-block",
          "@babel/plugin-proposal-class-properties",
        ],
      },
    }),
  ],
});

通过上面代码的构建我们就可以在开发的过程中使用装饰器的语法来进行开发了。

实现简单todoList

实现简单列表

首先我们需要先注册一个web Components组件,使用装饰器的语法是十分简单的,只需要通过装饰器定义即可。

javaScript 复制代码
@customElement("todo-list")
export class TodoList extends LitElement {}

接下来让我们渲染这个简单列表

javaScript 复制代码
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
@customElement("todo-list")
export class TodoList extends LitElement {
  @state()
  accessor textList = ["tdo1",'todo2', "todo3"];
  render() {
    return html`
        <ul>
        ${this.textList.map((item,index) => {
          return html`<li>${item}</li> `;
        })}
      </ul>
    `;
  }
}
html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Lit demo</title>
  </head>
  <body>
    <todo-list></todo-list>
    <script type="module" src="/src/index.js"></script>
  </body>
</html>

这样一来我们的列表就渲染在的浏览器上,通过上面的例子我为你介绍几个关于Lit的API @state() 内部反应状态,通常来说我们都可以使用@state来定义我们的变量 html将模版的文字解释为HTML模版,也就是说我们需要渲染的Dom 元素都需要通过字符串包裹交由html来进行处理。

接下来就让我们正式的实现todoList

为了让整个组件看起来更清晰,我们新建component文件夹,将input和列表各自拆分为独立的组件 在component中新建 data-list.jsinput.jsinput组件中实现对列表数据的添加

javaScript 复制代码
//src/component/input.js
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
​
@customElement("todo-list-input")
  export class SimpleGreeting extends LitElement {
    @state()
    accessor onClick;
​
    @state()
    accessor text = "";
​
    render() {
      return html`
      <input
        .value=${this.text}
        @input=${(e) => {
          this.text = e.target.value;
        }}
      />
​
      <button
        @click=${() => {
          this.onClick(this.text);
          this.text = "";
        }}
      >
        add
      </button>
    `;
    }
  }

data-list组件实现数据的渲染和删除逻辑

javaScript 复制代码
// src/component/data-list.js
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
​
@customElement("todo-data-list")
export class DataList extends LitElement {
  @state()
  accessor textList;
​
  @state()
  accessor del;
  
  render() {
    return html`
      <ul>
        ${this.textList.map((item,index) => {
          return html`<li>${item} <button @click=${()=>{
            this.del(index)
          }}>del</button></li> `;
        })}
      </ul>
    `;
  }
}

接下来就是index组件,负责数据的流向管理

javaScript 复制代码
// src/index.js
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import "./component/input";
import "./component/data-list";
@customElement("todo-list")
export class TodoList extends LitElement {
  @state()
  accessor textList = ["tdo1",'todo2', "todo3"];

  add(text) {
    const arr = JSON.parse(JSON.stringify(this.textList));
    arr.push(text);
    this.textList = arr;
  }

  del(index){
    const arr =  JSON.parse(JSON.stringify(this.textList)) 
     arr.splice(index,1)
    this.textList = arr
  }

  render() {
    return html`
      <div>
        <todo-list-input
          .onClick=${(val) => {
            this.add(val);
          }}
        ></todo-list-input>
        <todo-data-list .textList=${this.textList} .del=${(val)=>{

           this.del(val) 
        }}></todo-data-list>
      </div>
    `;
  }
}

自此通过这里例子我们实现了一个Lit组件完整的数据双向绑定和组件之间的父子通信。

总结

在上面的案例中还是有一些细节需要我们注意的

第一 在Lit 中引用数据类型的更新是不会触发渲染的,所以在案例中我们先使用JSON.parse(JSON.string())来对数据进行一次拷贝,从而触发视图的更新

第二 .操作Properties ,因为Lit目前国内相关介绍很少,按照我的理解我会以及目前的使用习惯我会把.理解为React中的props ,与props不同的是 Lit中通过.来传递的数据是可以改变的,并且当你通过.来传递函数到子组件时,this也会指向子组件

相关推荐
GoldKey2 小时前
gcc 源码阅读---语法树
linux·前端·windows
Xf3n1an3 小时前
html语法
前端·html
张拭心3 小时前
亚马逊 AI IDE Kiro “狙击”Cursor?实测心得
前端·ai编程
漠月瑾-西安4 小时前
如何在 React + TypeScript 中实现 JSON 格式化功能
javascript·jst实现json格式化
烛阴4 小时前
为什么你的Python项目总是混乱?层级包构建全解析
前端·python
止观止4 小时前
React响应式组件范式:从类组件到Hooks
javascript·react.js·ecmascript
@大迁世界4 小时前
React 及其生态新闻 — 2025年6月
前端·javascript·react.js·前端框架·ecmascript
LJianK15 小时前
Java和JavaScript的&&和||
java·javascript·python
红尘散仙5 小时前
Rust 终端 UI 开发新玩法:用 Ratatui Kit 轻松打造高颜值 CLI
前端·后端·rust
新酱爱学习5 小时前
前端海报生成的几种方式:从 Canvas 到 Skyline
前端·javascript·微信小程序