ข้ามไปยังเนื้อหา

LitElement

LitElement คือ base class ที่ extend จาก HTMLElement มาตรฐาน ซึ่งให้สามสิ่งหลัก:

  1. Reactive properties — ประกาศใน static properties และ Lit จะ watch การเปลี่ยนแปลงเพื่อ schedule re-render
  2. Declarative render — เมธอด render() คืน TemplateResult จาก html tagged template literal
  3. Scoped styles — ประกาศใน static styles ด้วย css tagged template literal และ Lit จะนำเข้าสู่ Shadow DOM

การประกาศ property ใน static properties ทำให้ Lit รู้ว่าต้อง watch property นั้น:

static properties = {
label: { type: String },
count: { type: Number },
};

เมื่อ this.count เปลี่ยนค่า Lit จะ schedule microtask update และเรียก render() โดยอัตโนมัติ

render() ต้องคืน TemplateResult ที่สร้างด้วย html tagged template literal:

render() {
return html`
<h3>${this.label}</h3>
<span>${this.count}</span>
<button @click=${() => this.count++}>+1</button>
`;
}

Lit จะ diff TemplateResult นี้กับ DOM ที่มีอยู่ และอัปเดตเฉพาะส่วนที่เปลี่ยนแปลง

ใช้ css tagged template literal ใน static styles เพื่อกำหนด styles:

static styles = css`
:host { display: block; padding: 12px; }
button { background: #6200ee; color: #fff; }
`;

Lit จะนำ stylesheet นี้เข้าสู่ Shadow DOM ของ element ทำให้ styles ไม่รั่วออกไปหรือถูกรบกวนจากภายนอก

ดู component ที่รวม reactive properties, render และ scoped styles เข้าด้วยกัน:

ตัวเลือกBenefitCost
Reactive properties ของ Lit (static properties)Lit จัดการ dirty-checking, batching และ re-render ให้อัตโนมัติ ลด boilerplate ไปมากเมื่อเทียบกับการเขียนเองเพิ่ม runtime ประมาณ +5-6KB และมี behavior บางส่วน (เช่น microtask scheduling) ที่ต้องเรียนรู้เพิ่ม
จัดการ state และ re-render เองใน HTMLElementควบคุมทุก timing ได้เต็มที่ ไม่มี runtime เพิ่มต้องเขียน attribute parsing, dirty-checking และ DOM diffing เองทั้งหมดด้วยมือ
  • ลืมประกาศ property ใน static properties — ถ้าไม่ประกาศ Lit จะไม่ track ค่า ทำให้ตั้งค่าแล้ว UI ไม่ re-render ตาม
  • Mutate array/object ใน property โดยตรง เช่น this.items.push(x) แทนที่จะสร้าง reference ใหม่ — Lit เทียบค่าด้วย !== เป็นค่าเริ่มต้น จึงตรวจไม่พบว่าเปลี่ยนแปลง และไม่ re-render
  • ใส่ logic หนักไว้ใน render() โดยตรง แทนที่จะคำนวณ/cache ไว้ล่วงหน้า — เพราะ render() อาจถูกเรียกบ่อยกว่าที่คิด ทำให้ performance แย่ลงโดยไม่จำเป็น

💡 ตัวอย่างจากของจริง

Home Assistant — frontend ทั้งหมดของแพลตฟอร์ม home automation นี้สร้างจาก custom elements ที่ extend LitElement โดยตรง

Google Material Web — component ของ Material Design ใช้ reactive properties และ scoped styles ของ LitElement เป็นแกนหลักในการ implement ทุกตัว

การประกาศ property ใน static properties ทำอะไร?
html tagged template literal คืนค่าอะไร?
Lit กำหนดขอบเขต CSS ให้กับ shadow tree ของ component ได้อย่างไร?