如果对
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.js
和input.js
在input组件
中实现对列表数据的添加
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
也会指向子组件