การนิยาม Element
การ extend HTMLElement
หัวข้อที่มีชื่อว่า “การ extend HTMLElement”autonomous custom element ทุกตัวเริ่มต้นจาก ES class ที่ extend HTMLElement:
class HelloBadge extends HTMLElement { // lifecycle callbacks go here}class จะไม่มีชื่อหรือมีชื่อก็ได้ — ชื่อนั้นถูกใช้ภายในโดย JavaScript เท่านั้น ตัวตนสาธารณะของ element คือชื่อ tag ที่คุณลงทะเบียนไว้
การลงทะเบียนด้วย customElements.define
หัวข้อที่มีชื่อว่า “การลงทะเบียนด้วย customElements.define”เมธอด customElements.define รับอาร์กิวเมนต์ที่จำเป็นสองตัวและอาร์กิวเมนต์เสริมหนึ่งตัว:
customElements.define(tagName, constructor, options);// ^string ^class ^optional { extends: '...' }customElements.define('hello-badge', HelloBadge);หลังจากการเรียกนี้ browser จะรู้ว่า <hello-badge> ทุกตัวในเอกสารคืออินสแตนซ์ของ HelloBadge
กฎบังคับว่าต้องมีเครื่องหมายขีด
หัวข้อที่มีชื่อว่า “กฎบังคับว่าต้องมีเครื่องหมายขีด”ชื่อ tag ของ custom element ต้องมีเครื่องหมายขีด (hyphen) อย่างน้อยหนึ่งตัว นี่คือวิธีที่ browser ใช้แยกแยะ element ของคุณออกจาก element ที่มีมาในตัวทั้งในปัจจุบันและอนาคต:
<!-- valid custom element names --><hello-badge></hello-badge><my-app></my-app><x-button></x-button>
<!-- INVALID — no hyphen — the browser treats these as unknown built-ins --><hellobadge></hellobadge><mybadge></mybadge>คำนำหน้าที่สงวนไว้และคุณใช้ไม่ได้: annotation-xml, color-profile, font-face, font-face-*
การนำ element ไปใช้ใน HTML
หัวข้อที่มีชื่อว่า “การนำ element ไปใช้ใน HTML”เมื่อนิยามแล้ว element จะทำงานเหมือน element เนทีฟทุกประการ — วางไว้ในมาร์กอัป กำหนด attribute และ query ด้วย JavaScript ได้เลย:
<hello-badge name="Alice"></hello-badge><hello-badge name="Bob"></hello-badge>const badge = document.querySelector('hello-badge');badge.getAttribute('name'); // 'Alice'เดโมที่รันได้
หัวข้อที่มีชื่อว่า “เดโมที่รันได้”ลองเปลี่ยนค่า attribute name ในแผง HTML แล้วดูผลลัพธ์อัปเดตตาม
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
Native custom elements (customElements.define) | ไม่ผูกกับเฟรมเวิร์กใด ทำงานได้ทุกที่ที่มี DOM โดยไม่ต้องมี build step | DX ไม่ลื่นไหลเท่าเฟรมเวิร์กอย่าง React/Vue — ไม่มี JSX, ไม่มี reactive state ให้ในตัว ต้องจัดการเอง |
| ตั้งชื่อ tag ตามกฎ hyphen | browser แยกแยะ element ของคุณจาก element เนทีฟทั้งปัจจุบันและอนาคตได้ชัดเจน | ต้องคิดชื่อที่มีขีดเสมอ เพิ่มภาระเล็กน้อยตอนออกแบบ naming convention |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ตั้งชื่อ tag โดยไม่มีเครื่องหมายขีด — เช่น
mybadgebrowser จะปฏิเสธการลงทะเบียนหรือถือว่าเป็นHTMLUnknownElementแบบเงียบ ๆ - เรียก
customElements.define()ซ้ำด้วยชื่อ tag เดิม — จะโยน error ทันที ต้องเช็คด้วยcustomElements.get(tagName)ก่อนถ้าไม่แน่ใจว่าลงทะเบียนไปแล้วหรือยัง - ใช้คำนำหน้าที่สงวนไว้ — เช่น
font-face-*หรือannotation-xmlจะลงทะเบียนไม่ได้เพราะสเปกกันไว้ให้ใช้ในอนาคต
💡 ตัวอย่างจากของจริง
YouTube — ฟรอนต์เอนด์ทั้งเว็บสร้างขึ้นบน custom elements ภายในระบบของตัวเอง ผ่านการเรียก
customElements.defineจำนวนมากสำหรับแต่ละ componentGitHub — ลงทะเบียน element อย่าง
<relative-time>ด้วยชื่อที่มีขีดตามกฎสเปก แล้วนำไปใช้ตรง ๆ ใน HTML ของหน้าเว็บจริง