Web Components คือองค์ประกอบที่กำหนดเอง, Shadow DOM และเทมเพลต HTML ซึ่งเป็นองค์ประกอบพื้นฐานของแพลตฟอร์มสำหรับคอมโพเนนต์ที่นำกลับมาใช้ใหม่ได้และไม่ขึ้นอยู่กับเฟรมเวิร์ก โดยมาร์กอัปและสไตล์จะได้รับการแคปซูลจากเอกสาร ใช้สำหรับระบบการออกแบบ วิดเจ็ตที่ฝังได้ และ UI แบบครบวงจร
กฎด้านล่างนี้เป็นกฎที่ครอบคลุมหลายด้าน ดูคำแนะนำที่เจาะจงสำหรับงานที่ทำอยู่ โดยแต่ละคำแนะนำจะระบุบริบทที่จำเป็นและบันทึก API และข้อผิดพลาดที่เฉพาะเจาะจงสำหรับงานนั้นๆ
ตัดสินใจว่าคุณจำเป็นต้องใช้องค์ประกอบที่กำหนดเองหรือไม่
ใช้องค์ประกอบที่กำหนดเองเฉพาะเมื่อคุณต้องการลักษณะการทำงานที่รวมไว้ วงจร หรือ API ที่สนับสนุน JS ที่นำกลับมาใช้ใหม่ได้ในแท็ก อย่าสร้างทักษะในกรณีต่อไปนี้
- องค์ประกอบ HTML ธรรมดาที่มี CSS ก็เพียงพอแล้ว
<button>หรือ<details>ที่มีสไตล์จะเข้าถึงได้ง่ายกว่าและมีค่าใช้จ่ายน้อยกว่าการติดตั้งใช้งานใหม่ - สิ่งนี้เป็นเพียงการนำเสนอเท่านั้น โดยไม่มีลักษณะการทำงานใดๆ คลาสในองค์ประกอบแบบเนทีฟมีประสิทธิภาพมากกว่า และกำหนดขอบเขตได้ด้วย
@layerหรือ@scope - คุณต้องการเพียงการกำหนดขอบเขตสไตล์บนเซิร์ฟเวอร์โดยไม่มีการโต้ตอบ สไตล์ชีตที่กำหนดขอบเขตหรือ Declarative Shadow DOM (โดยไม่มีการอัปเกรด) อาจเพียงพอแล้ว
การสร้างความหมายแบบเนทีฟขึ้นมาใหม่ (<my-button> ที่กำหนดเองซึ่งสร้างโฟกัส การเปิดใช้งาน และ ARIA ขึ้นมาใหม่) เป็นการใช้ในทางที่ผิดที่พบบ่อยที่สุด คุณจะรับช่วงการช่วยเหลือพิเศษของแพลตฟอร์มได้โดยไม่มีค่าใช้จ่ายก็ต่อเมื่อคุณนำองค์ประกอบแบบเนทีฟมาใช้ซ้ำเท่านั้น เมื่อ Wrapper สไตล์ <my-button> ได้รับการรับประกัน ซึ่งโดยปกติแล้วจะเป็นฮุกการจัดสไตล์ที่ใช้ร่วมกัน มาร์กอัปเพิ่มเติม หรือลักษณะการทำงานที่องค์ประกอบแบบเนทีฟแสดงไม่ได้ ให้รวม <button> จริงแทนที่จะนำไปใช้ใหม่ (ดูการจัดสไตล์คอมโพเนนต์เว็บสำหรับการส่งต่อสไตล์ไปยังองค์ประกอบแบบเนทีฟภายใน)
การทดสอบคือคุณต้องการสถานะที่ห่อหุ้ม, API ที่เขียนสคริปต์ได้ หรือลักษณะการทำงานที่องค์ประกอบเนทีฟแสดงไม่ได้หรือไม่ ไม่ใช่แค่รูปลักษณ์ที่แตกต่างกัน ปุ่มเปิด/ปิดการกดชอบ/รายการโปรดมีคุณสมบัติตรงตามเกณฑ์ โดยจะเก็บสถานะโดเมนที่เชื่อมโยงไว้ แสดงสถานะดังกล่าวเป็นฮุกการจัดรูปแบบสำหรับหน้าเว็บโดยรอบ และส่งเหตุการณ์ change ของตัวเอง ซึ่ง <button> ที่จัดรูปแบบแล้วไม่มีให้ ปุ่มที่เปลี่ยนสีเมื่อกดเท่านั้นจะไม่เปลี่ยนสี ให้ใช้ <button> + CSS เมื่อสร้าง ให้จำลองสถานะด้วยสถานะหรือแอตทริบิวต์ที่กำหนดเองตามความเหมาะสม (ดูองค์ประกอบที่กำหนดเอง)
จับคู่เครื่องมือกับฐานของโค้ด
การที่บางสิ่งควรเป็นองค์ประกอบที่กำหนดเองหรือไม่นั้นขึ้นอยู่กับสิ่งที่โปรเจ็กต์ใช้อยู่แล้ว เอเจนต์มักจะสรุปมากเกินไปและพยายามเข้าถึงองค์ประกอบใหม่มากเกินไป เมื่อมีข้อสงสัย ตัวเลือกที่เบากว่า (องค์ประกอบเนทีฟ, CSS, เทมเพลตเซิร์ฟเวอร์) มักจะถูกต้อง และคุณสามารถโปรโมตเป็นองค์ประกอบที่กำหนดเองในภายหลังได้หากการนำกลับมาใช้ใหม่หรือลักษณะการทำงานต้องการจริงๆ การคาดคะเนตามลำดับความสำคัญคร่าวๆ มีดังนี้
- ฐานของโค้ดมีโมเดลคอมโพเนนต์ (React, Vue, Svelte, …) อยู่แล้ว ให้ใช้คอมโพเนนต์ของเฟรมเวิร์กนั้นเป็นค่าเริ่มต้นสำหรับ UI ในแอป ใช้องค์ประกอบที่กำหนดเองเฉพาะเมื่อสิ่งนั้นต้องหลุดออกจากเฟรมเวิร์กหรือมีอายุการใช้งานนานกว่าเฟรมเวิร์ก เช่น องค์ประกอบพื้นฐานของระบบการออกแบบที่แชร์ในแอปหรือเฟรมเวิร์กต่างๆ วิดเจ็ตที่วางลงในมาร์กอัปที่เฟรมเวิร์กไม่ได้ควบคุม หรือเอาต์พุตที่ต้องทำงานเป็น HTML ธรรมดา (อีเมล, CMS, ส่วนย่อย SSR) อย่าสร้างระบบคอมโพเนนต์แบบขนานสำหรับข้อมูลพร็อพเพอร์ตี้แอปทั่วไป
- ไม่มีเครื่องมือ ส่วนใหญ่เป็นมาร์กอัปแบบคงที่ ใช้ HTML + CSS ธรรมดา หรือเทมเพลต/บางส่วนของเซิร์ฟเวอร์ องค์ประกอบที่กำหนดเองจะคุ้มค่าก็ต่อเมื่อคุณต้องการพฤติกรรม, วงจร หรือ API ที่สนับสนุน JS ในแท็กจริงๆ ไม่ใช่เพียงเพื่อแชร์มาร์กอัป ซึ่งเซิร์ฟเวอร์รวมหรือ
<template>ทำได้โดยไม่ต้องส่ง JS ใดๆ - เครื่องมือสร้างเว็บไซต์แบบคงที่ซึ่งมีเกาะแห่งการโต้ตอบ แสดงผลมาร์กอัปแบบคงที่ และสงวนองค์ประกอบที่กำหนดเองไว้สำหรับส่วนที่มีการโต้ตอบ สำหรับ "มาร์กอัปจำนวนมากที่มีการโต้ตอบเพียงเล็กน้อย" ให้เก็บมาร์กอัปไว้ใน Light DOM (หรือ Declarative Shadow DOM) และปล่อยให้องค์ประกอบที่กำหนดเองขนาดเล็กปรับปรุงมาร์กอัปอย่างต่อเนื่อง แทนที่จะแสดงผลทุกอย่างจาก JS อีกครั้ง
- คุณสามารถผลักดันองค์ประกอบที่มีอยู่แล้วให้ดียิ่งขึ้นแทนได้ การใช้องค์ประกอบแบบเนทีฟให้มากที่สุด (CSS, Listener บางรายการ, องค์ประกอบจำลองเป็นครั้งคราว) มักจะดีกว่าองค์ประกอบที่กำหนดเอง เนื่องจากคุณจะคงการช่วยเหลือพิเศษและลักษณะการทำงานของแพลตฟอร์มไว้ได้โดยไม่มีค่าใช้จ่าย เปลี่ยนไปใช้องค์ประกอบที่กำหนดเองเมื่อวิธีแก้ปัญหาชั่วคราวไม่สามารถดูแลรักษาได้อีกต่อไป เช่น เมื่อคุณต้องต่อสู้กับลักษณะการทำงานในตัวขององค์ประกอบ หรือประสบการณ์การเขียนแย่กว่า API คอมโพเนนต์ที่สะอาด การที่ต้องใช้ JS เล็กน้อยในองค์ประกอบในตัวไม่ได้เป็นเหตุผลในการแทนที่องค์ประกอบนั้น
กฎที่ใช้ร่วมกัน
โดยหลักการเหล่านี้มีผลกับคำแนะนำทั้งหมดด้านล่าง
- บังคับ: ชื่อแท็กต้องเป็น kebab-case ที่มีขีดกลางอย่างน้อย 1 ขีด (เช่น
my-element) ซึ่งจะช่วยแยกองค์ประกอบที่กำหนดเองออกจากองค์ประกอบในตัวทั้งในปัจจุบันและอนาคต - บังคับ: เรียก
super()ก่อนใน Constructor ก่อนที่จะแตะthisการเรียกหลังจากคำสั่งใดๆ ที่อ่านหรือเขียนthisจะแสดงข้อผิดพลาด - บังคับ: ใช้องค์ประกอบเชิงความหมาย (
<button>,<nav>,<ul>) ภายในเทมเพลตเงา ความล้มเหลวด้านการช่วยเหลือพิเศษส่วนใหญ่ใน Shadow Tree มาจากมาร์กอัปที่ไม่ใช่เชิงความหมาย ช่องไม่ได้เปลี่ยนบทบาทของสิ่งที่ฉาย - บังคับ: การอ้างอิง ARIA
id(aria-labelledby,aria-describedby,aria-controls) ไม่สามารถข้ามขอบเขต Shadow ได้ องค์ประกอบที่อ้างอิงและidที่ชี้ไปต้องอยู่ในแผนผังเดียวกัน - แนะนำให้ใช้
attachShadow({ mode: 'open' })เพื่อให้เครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ สคริปต์หน้าเว็บ และการไฮเดรตเซิร์ฟเวอร์เข้าถึงelement.shadowRootได้ ใช้'closed'เฉพาะเมื่อคุณต้องซ่อนโครงสร้างภายในจากสคริปต์หน้าเว็บ - หลีกเลี่ยงองค์ประกอบในตัวที่กำหนดเอง (
extends HTMLButtonElementที่มีis="…") เนื่องจาก Safari ปฏิเสธที่จะจัดส่งองค์ประกอบดังกล่าวอย่างถาวร
เมทริกซ์คู่มือกรณีการใช้งาน
ระบุงานและดึงข้อมูลคู่มือของงานนั้นๆ โดยทำดังนี้
| หากต้องการ… | ดึงข้อมูล |
|---|---|
| กำหนดแท็กเชิงความหมายใหม่พร้อมลักษณะการทำงานและวงจร | องค์ประกอบที่กำหนดเอง |
| กำหนดขอบเขตสไตล์และมาร์กอัปให้กับคอมโพเนนต์ และฉายเนื้อหาของผู้บริโภคลงในคอมโพเนนต์ | Shadow DOM, เทมเพลต และสล็อต |
| แสดงผล Shadow Tree ของคอมโพเนนต์บนเซิร์ฟเวอร์ (SSR) โดยไม่มีเนื้อหาที่ไม่มีการจัดรูปแบบปรากฏขึ้นมาแวบหนึ่ง | การแสดงผลองค์ประกอบที่กำหนดเองล่วงหน้า |
จัดรูปแบบข้ามขอบเขต Shadow (การกำหนดธีม, ::part, คุณสมบัติที่กำหนดเอง) |
การจัดรูปแบบคอมโพเนนต์เว็บ |
ส่งค่าของตัวควบคุมที่กำหนดเองไปยัง <form> โดยรอบ |
องค์ประกอบที่กำหนดเองที่เชื่อมโยงกับแบบฟอร์ม |
| ทำให้องค์ประกอบที่กำหนดเองเข้าถึงได้ (บทบาท, โฟกัส, ARIA ใน Shadow Root) | คอมโพเนนต์เว็บที่เข้าถึงได้ |