เชี่ยวชาญวงจรชีวิตของ custom element การห่อหุ้มด้วย shadow DOM และการฉายเนื้อหาผ่าน slots
เปิดบทเรียนนี้ใน KodokonCustom elements ขยายคลังคำศัพท์ของ HTML: คลาสใด ๆ ที่สืบทอดจาก HTMLElement สามารถลงทะเบียนใน CustomElementRegistry ได้ ตราบใดที่ชื่อของมันมีเครื่องหมายขีด (user-badge ไม่ใช่ userbadge) จุดละเอียด: หากแท็กปรากฏในเอกสารก่อนที่จะเรียก customElements.define มันจะถูกสร้างเป็นองค์ประกอบที่ไม่รู้จัก (unknown element) ก่อน แล้วจึงถูก upgrade ในที่: constructor จะถูกเรียกในภายหลังบนโหนดที่มีอยู่ในต้นไม้แล้ว
class UserBadge extends HTMLElement {
static observedAttributes = ["name"];
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
this.textContent = this.getAttribute("name");
}
}
customElements.define("user-badge", UserBadge);วงจรชีวิตมีกับดักอยู่บ้าง: attributeChangedCallback จะทำงานเฉพาะกับแอตทริบิวต์ที่ระบุไว้ใน observedAttributes เท่านั้น และระหว่างการ upgrade มันจะถูกเรียกสำหรับทุกแอตทริบิวต์ที่มีอยู่แล้ว ก่อน connectedCallback ข้อกำหนดห้าม constructor ตรวจสอบแอตทริบิวต์และลูก ๆ หรือเพิ่มสิ่งใด: ในขณะที่มันทำงาน (ผ่าน createElement หรือการโคลน) องค์ประกอบอาจว่างเปล่าโดยสิ้นเชิง
<template id="card-tpl">
<style>
:host { display: block; padding: 1rem; }
::slotted(h2) { margin: 0; }
</style>
<slot name="title"></slot>
<slot></slot>
</template>attachShadow สร้างต้นไม้ย่อยที่ถูกห่อหุ้ม: สไตล์ไม่รั่วออกจากมัน ตัวเลือกของหน้าเว็บเข้าถึงมันไม่ได้ - มีเพียงคุณสมบัติ CSS ที่สืบทอดได้ (color, font) และ custom properties เท่านั้นที่ข้ามขอบเขตได้ เนื้อหาของ <template> อาศัยอยู่ใน DocumentFragment ที่เข้าถึงได้ผ่าน .content: สคริปต์ของมันไม่ทำงานและรูปภาพของมันไม่โหลดจนกว่าคุณจะโคลนมันเข้าไปในเอกสาร โหนดที่วางไว้ใน light DOM จะถูก ฉาย (projected) เข้าไปในองค์ประกอบ <slot>: พวกมันยังคงอยู่ใน light DOM ทางกายภาพ และเหตุการณ์ slotchange จะแจ้งให้คุณทราบถึงการเปลี่ยนแปลงใด ๆ ในการกำหนด (assignment)
class InfoCard extends HTMLElement {
constructor() {
super();
const tpl = document.getElementById("card-tpl");
this.attachShadow({ mode: "open" })
.appendChild(tpl.content.cloneNode(true));
}
}
customElements.define("info-card", InfoCard);ส่วนขยายสองอย่างสมควรได้รับความสนใจจากคุณ Form-associated custom elements: ด้วย static formAssociated = true และ attachInternals() คอมโพเนนต์ของคุณจะมีส่วนร่วมในฟอร์มอย่างเต็มที่ (ค่าที่ส่ง การตรวจสอบความถูกต้องแบบเนทีฟ สถานะ :invalid) และ declarative shadow DOM: <template shadowrootmode=open> จะแนบ shadow root ในเวลา parse โดยไม่ต้องใช้ JavaScript ซึ่งทำให้ web components เข้ากันได้กับการเรนเดอร์ฝั่งเซิร์ฟเวอร์
attachShadow({ mode: 'closed' }) แล้ว element.shadowRoot ส่งคืนอะไรจากภายนอก?null: มีเพียงการอ้างอิงที่ส่งคืนจาก attachShadow เท่านั้นที่ให้เข้าถึง shadow root ได้<slot> อาศัยอยู่ที่ไหนทางกายภาพ?