litelement已封装响应式属性、模板渲染、样式隔离和生命周期,直接使用可避免手动处理attribute同步、requestupdate调用及shadow dom样式注入等繁琐逻辑。

直接用 LitElement 就行,别绕路写原生 Custom Elements + lit-html 组合——LitElement 已经把响应式属性、模板渲染、样式封装、生命周期钩子全打包好了,手动拼接反而容易漏掉 attributeChangedCallback 同步逻辑或忘记调用 requestUpdate()。
为什么不能直接用 lit-html + HTMLElement
你确实能用 lit-html 渲染到 shadowRoot,但会立刻撞上三个硬伤:
- 属性变更不会自动触发重渲染:原生
HTMLElement没有 reactive 系统,改了this.count,render()不会自己跑 - HTML 属性(attribute)和 JS 属性(property)不同步:比如
<my-counter count="5"></my-counter>,你得手动在observedAttributes和attributeChangedCallback里 parse、赋值、再requestUpdate() - 样式无法自动 scoped:
lit-html本身不处理 CSS,你得自己appendChildstyle 标签或靠adoptedStyleSheets,而LitElement的static styles会自动注入到 shadow root
必须用 @customElement 装饰器注册
不加 @customElement('my-button') 或等价的 customElements.define('my-button', MyButton),浏览器根本不认这是个合法自定义元素——哪怕类继承了 LitElement。常见错误是只写了类、忘了注册,然后在 HTML 里写 <my-button></my-button> 却没反应,控制台也无报错。
注意命名规则:my-button 合法,mybutton 或 MyButton 都非法,浏览器会直接抛 DOMException: "The element name must contain a hyphen"。
property 类型声明决定 attribute 可否序列化
static properties 不只是为了类型提示,它直接控制 Lit 如何同步 attribute ↔ property:
-
count: { type: Number }→ 浏览器会把count="42"自动转成数字,且修改this.count = 100会反向更新 attribute(如果reflect: true) -
items: { type: Array }→ attribute 不支持传数组,<my-list items='["a","b"]'></my-list>会被当字符串解析;这种场景必须用 JS property 传值,比如el.items = [1,2,3] - 没声明
type的 property(如@property() label)默认为String,且不 reflect 到 attribute,适合内部状态
别指望 JSON.stringify 过的字符串能被自动还原成对象——Lit 不做这层解析,那是你自己的 attributeChangedCallback 该干的事(但用了 LitElement 就不该这么干)。
authentik 项目里必须继承 AKElement 而非 LitElement
如果你在 authentik 代码库中开发组件,AKElement 是封装好的基类,位于 web/src/elements/Base.ts。它已预置主题变量(--ak-color-primary)、全局样式重置、以及和 authentik 后端通信的快捷方法。
直接继承 LitElement 会导致:
- 主题色失效:CSS 中的
var(--ak-color-primary)没定义,显示为 fallback 值(通常是inherit或initial) - 缺少
connectedCallback中的初始化钩子(如 token 检查、i18n 加载),可能引发后续 API 调用失败 - 构建时样式未被统一打包进
base.css,导致本地开发正常、CI 构建后样式丢失
正确写法是:import { AKElement } from '#elements/Base';,然后 export class AkLoginButton extends AKElement。
最常被忽略的是:LitElement 的 render() 方法必须返回 html 模板,不能返回字符串或空值;一旦返回 undefined 或 null,整个 shadow DOM 会清空,且不报错——这个静默失败很难定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











