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

การนิยาม Element

autonomous custom element ทุกตัวเริ่มต้นจาก ES class ที่ extend HTMLElement:

class HelloBadge extends HTMLElement {
// lifecycle callbacks go here
}

class จะไม่มีชื่อหรือมีชื่อก็ได้ — ชื่อนั้นถูกใช้ภายในโดย JavaScript เท่านั้น ตัวตนสาธารณะของ element คือชื่อ tag ที่คุณลงทะเบียนไว้

เมธอด 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>

ชื่อที่สงวนไว้และใช้ไม่ได้ แม้จะมีขีดอยู่ก็ตาม (เป็นของ SVG/MathML): annotation-xml, color-profile, font-face, font-face-src, font-face-uri, font-face-format, font-face-name, missing-glyph

เมื่อนิยามแล้ว 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 แล้วดูผลลัพธ์อัปเดตตาม

ตัวเลือกBenefitCost
Native custom elements (customElements.define)ไม่ผูกกับเฟรมเวิร์กใด ทำงานได้ทุกที่ที่มี DOM โดยไม่ต้องมี build stepDX ไม่ลื่นไหลเท่าเฟรมเวิร์กอย่าง React/Vue — ไม่มี JSX, ไม่มี reactive state ให้ในตัว ต้องจัดการเอง
ตั้งชื่อ tag ตามกฎ hyphenbrowser แยกแยะ element ของคุณจาก element เนทีฟทั้งปัจจุบันและอนาคตได้ชัดเจนต้องคิดชื่อที่มีขีดเสมอ เพิ่มภาระเล็กน้อยตอนออกแบบ naming convention
  • ตั้งชื่อ tag โดยไม่มีเครื่องหมายขีด — เช่น mybadge browser จะปฏิเสธการลงทะเบียนหรือถือว่าเป็น HTMLUnknownElement แบบเงียบ ๆ
  • เรียก customElements.define() ซ้ำด้วยชื่อ tag เดิม — จะโยน error ทันที ต้องเช็คด้วย customElements.get(tagName) ก่อนถ้าไม่แน่ใจว่าลงทะเบียนไปแล้วหรือยัง
  • ใช้ชื่อที่สงวนไว้ — เช่น font-face-src หรือ annotation-xml จะลงทะเบียนไม่ได้เพราะสเปกกันชื่อเหล่านี้ไว้ให้ SVG/MathML

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

GitHub — ลงทะเบียน element อย่าง <relative-time> ด้วยชื่อที่มีขีดตามกฎสเปก แล้วนำไปใช้ตรง ๆ ใน HTML ของหน้าเว็บจริง (github/relative-time-element)

Google Material Web — แต่ละ component ของ Material Design แยกเป็นโมดูลของตัวเองที่เรียก customElements.define เอง ทำให้ผู้ใช้ import และลงทะเบียนเฉพาะ component ที่ต้องการ (material-components/material-web)

ชื่อ tag ใดเป็นชื่อ autonomous custom element ที่ถูกต้อง?
อาร์กิวเมนต์ตัวแรกของ customElements.define คืออะไร?
browser ทำอะไรเมื่อพบชื่อ tag ที่ถูกลงทะเบียนไว้กับ customElements.define แล้ว?