การใช้ใน Frameworks
Web components คือ DOM elements ธรรมดา
หัวข้อที่มีชื่อว่า “Web components คือ DOM elements ธรรมดา”custom element ที่ลงทะเบียนด้วย customElements.define คือ DOM node มาตรฐาน framework ใดก็ตามที่สร้าง HTML ก็ใช้ได้ คุณวางไว้ใน JSX, Vue template หรือ Angular template ได้เช่นเดียวกับที่คุณวาง <div>
เนื่องจาก frameworks สร้าง DOM nodes จริงในท้ายที่สุด ทุก framework จึงทำงานร่วมกับ custom elements ได้ในระดับเดียวกัน — element API ของ browser เอง Properties, attributes และ events ทำงานเหมือนกันโดยไม่ขึ้นกับ framework ที่เรนเดอร์ tree โดยรอบ
React 18 และก่อนหน้า
หัวข้อที่มีชื่อว่า “React 18 และก่อนหน้า”ใน React 18 และก่อนหน้านั้น custom elements รับ string attributes ไม่ใช่ rich object props ส่งค่า primitives (strings, numbers, booleans) เป็น attributes สำหรับข้อมูลที่ซับซ้อน (arrays, objects) หรือการฟัง custom events คุณต้องใช้ ref callback:
// React 18 — attach ref to wire up eventsimport { useRef, useEffect } from 'react';
function App() { const ref = useRef(null); useEffect(() => { const el = ref.current; el.addEventListener('my-event', (e) => console.log(e.detail)); return () => el.removeEventListener('my-event', () => {}); }, []); return <my-counter ref={ref} label="Score"></my-counter>;}React 19
หัวข้อที่มีชื่อว่า “React 19”React 19 มาพร้อมการรองรับ custom element อย่างเต็มรูปแบบ Properties และ event handlers (ที่นำหน้าด้วย on) ตอนนี้ผูกกันโดยตรงโดยไม่ต้องใช้ ref workaround:
// React 19 — direct prop and event bindingfunction App() { return ( <my-counter label="Score" count={0} onmy-event={(e) => console.log(e.detail)} /> );}Vue ถือว่า custom elements เป็นพลเมืองชั้นหนึ่ง Attributes และ properties ผูกกันด้วย :prop="value" (property) หรือ attr="value" (attribute) Custom events ฟังด้วย @event-name:
<!-- Vue template --><my-counter :label="label" :count="score" @score-changed="handleChange"/>Vue แยกแยะโดยอัตโนมัติว่าจะตั้งค่าเป็น property (set บน DOM node) หรือ attribute (set ผ่าน setAttribute) โดยดูจากว่า key นั้นมีอยู่ใน prototype ของ element หรือไม่
Angular
หัวข้อที่มีชื่อว่า “Angular”Angular รองรับ custom elements ผ่าน CUSTOM_ELEMENTS_SCHEMA เพิ่ม schema นี้เข้าไปใน array schemas ของ module เพื่อปิด error ของ unknown-element:
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
@NgModule({ declarations: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA],})export class AppModule {}ใน templates ใช้ [property] สำหรับ property binding และ (event-name) สำหรับ custom events:
<!-- Angular template --><my-counter [label]="title" [count]="score" (score-changed)="onScoreChanged($event)"></my-counter>ตัวอย่างที่รันได้
หัวข้อที่มีชื่อว่า “ตัวอย่างที่รันได้”ตัวอย่างด้านล่างแสดง vanilla web component (<demo-badge>) ที่เรนเดอร์ใน HTML ธรรมดา — element เดียวกันนี้จะทำงานได้เหมือนกันทุกประการเมื่อวางใน React, Vue หรือ Angular tree เพราะเป็นแค่ DOM node
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
ใช้ native interop ของ framework ตรงๆ (เช่น React 19 direct binding, Vue :prop) | ไม่มี dependency เพิ่ม, bundle เล็กลง และใช้ API มาตรฐานของ browser ล้วนๆ | ต้องจัดการ complex props/events เอง โดยเฉพาะบน React 18 ที่ต้องพึ่ง ref |
ใช้ wrapper library เช่น @lit/react | ได้ typed component พร้อม props/events ที่ผูกให้อัตโนมัติ ลด boilerplate ฝั่งผู้ใช้ | เพิ่ม dependency และ layer พิเศษที่ต้องดูแลให้ตรงกับเวอร์ชันของ element เดิม |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- สร้าง wrapper component ขึ้นมาเองทั้งที่ framework รองรับ native interop อยู่แล้ว (เช่น React 19) — เพิ่ม layer และโค้ดดูแลรักษาที่ไม่จำเป็น ทั้งที่ผูก property/event ตรงได้เลย
- ส่ง array/object เป็น JSX attribute บน React 18 แล้วงงว่าทำไมค่าไม่ถูกต้อง — React 18 และก่อนหน้าจะแปลงทุกอย่างเป็น string attribute ต้องใช้
refตั้งค่า property โดยตรง หรืออัปเกรดเป็น React 19 - ผูก custom event ด้วย attribute syntax ปกติแทน syntax เฉพาะของ framework — ลืมใช้
@event-nameใน Vue หรือ(event-name)ใน Angular ทำให้ event handler ไม่ถูกเรียกเลย
💡 ตัวอย่างจากของจริง
Google Material Web — เอกสารของโปรเจกต์สาธิตการใช้ component เดียวกันข้าม React, Angular และ Vue โดยไม่ต้องเขียน wrapper แยกสำหรับแต่ละ framework
Home Assistant — ฝัง custom elements ที่สร้างจาก Lit ไว้ใน dashboard UI ที่ผสมกับโค้ด frontend อื่นๆ ได้โดยตรงผ่าน native DOM interop