องค์ประกอบที่กำหนดเองช่วยให้คุณสร้างแท็ก HTML ของคุณเองได้ รายการตรวจสอบนี้ครอบคลุมแนวทางปฏิบัติแนะนำเพื่อช่วยคุณสร้างองค์ประกอบที่มีคุณภาพสูง
องค์ประกอบที่กำหนดเองช่วยให้คุณขยาย HTML และกำหนดแท็กของคุณเองได้ เป็น
เป็นฟีเจอร์ที่มีประสิทธิภาพอย่างเหลือเชื่อ แต่อยู่ในระดับต่ำเช่นกัน ซึ่งหมายความว่า
ควรทราบวิธีที่ดีที่สุดในการใช้งานองค์ประกอบของคุณเอง
เพื่อช่วยคุณสร้างประสบการณ์ที่ดีที่สุด เราได้รวบรวมข้อมูลนี้เข้าด้วยกัน
รายการตรวจสอบ ได้แตกลายทุกสิ่งที่เราคิดว่า จำเป็นต่อการเป็น
องค์ประกอบที่กำหนดเองและทำงานได้ดี
เช็กลิสต์
Shadow DOM
  
    
      สร้างรากเงาเพื่อสรุปรูปแบบ | 
    
    
      | เพราะเหตุใด | 
      
  รูปแบบการห่อหุ้มในรากเงาขององค์ประกอบจะช่วยให้มั่นใจได้ว่ารูปแบบนั้นจะทำงาน
  ไม่ว่าจะใช้งานอยู่ที่ใด ซึ่งสำคัญมากหากนักพัฒนาแอป
  ต้องการวางองค์ประกอบของคุณไว้ภายในรากเงาขององค์ประกอบอื่น ช่วงเวลานี้
  ใช้ได้กับองค์ประกอบง่ายๆ เช่น ช่องทำเครื่องหมายหรือปุ่มตัวเลือก อาจจะเป็น
  ในกรณีนี้ เนื้อหาเดียวภายในรากเงาของคุณจะเป็นรูปแบบ
  ด้วยตนเอง
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
  
    
      
        สร้างรากเงาในเครื่องมือสร้าง
       | 
    
    
      | เพราะเหตุใด | 
      
  เครื่องมือสร้างคือเมื่อคุณมีความรู้เฉพาะตัวเกี่ยวกับองค์ประกอบนั้นๆ
  ตอนนี้เป็นเวลาที่เหมาะสมในการตั้งค่ารายละเอียดการใช้งานที่คุณไม่ต้องการ
  องค์ประกอบที่มีอยู่มากมาย การดำเนินการนี้จะดำเนินการในการเรียกกลับในภายหลัง เช่น
  connectedCallback ซึ่งหมายความว่าคุณจะต้องป้องกัน
  สถานการณ์ที่องค์ประกอบของคุณถูกแยกออก แล้วแนบกับเอกสารอีกครั้ง
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
  
    
      
        วางองค์ประกอบย่อยที่องค์ประกอบสร้างขึ้นลงในรากที่เป็นเงา
       | 
    
    
      | เพราะเหตุใด | 
      
  องค์ประกอบย่อยที่องค์ประกอบสร้างขึ้นเป็นส่วนหนึ่งของการใช้งาน และควรเป็น
  ส่วนตัว หากปราศจากการป้องกันของรากที่มืด JavaScript ภายนอกอาจ
  และรบกวนเด็กเหล่านี้โดยไม่ได้ตั้งใจ
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-tabs>
       | 
    
  
  
    
      
        ใช้ <slot> เพื่อฉายภาพย่อยของ Light DOM เข้าไปใน Shadow DOM
       | 
    
    
      | เพราะเหตุใด | 
      
        อนุญาตให้ผู้ใช้ของคอมโพเนนต์ระบุเนื้อหาในคอมโพเนนต์เนื่องจากองค์ประกอบย่อย HTML ทำให้คอมโพเนนต์สามารถเขียนได้ง่ายขึ้น เมื่อเบราว์เซอร์ไม่รองรับองค์ประกอบที่กำหนดเอง เนื้อหาที่ซ้อนอยู่จะยังคงใช้งานได้ มองเห็นได้ และเข้าถึงได้
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-tabs>
       | 
    
  
  
    
      
        
  ตั้งค่ารูปแบบการแสดงผล :host (เช่น block,
  inline-block, flex) ยกเว้นกรณีที่คุณต้องการใช้ค่าเริ่มต้น
  inline
        
       | 
    
    
      | เพราะเหตุใด | 
      
  องค์ประกอบที่กำหนดเองจะเป็น display: inline โดยค่าเริ่มต้น ดังนั้นการตั้งค่าองค์ประกอบ
  widthหรือheightจะไม่มีผลใดๆ บ่อยครั้ง
  เป็นเรื่องน่าประหลาดใจสำหรับนักพัฒนาแอปและอาจทำให้เกิดปัญหาเกี่ยวกับ
  การจัดวางหน้าเว็บ หากคุณไม่ต้องการจอแสดงผลแบบ inline
  ควรกำหนดค่า display เริ่มต้นเสมอ
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
  
    
      
        
  เพิ่มรูปแบบการแสดงผล :host ที่ใช้แอตทริบิวต์ที่ซ่อนอยู่
        
       | 
    
    
      | เพราะเหตุใด | 
      
  องค์ประกอบที่กําหนดเองซึ่งมีรูปแบบ display เริ่มต้น เช่น
  :host { display: block } จะลบล้างค่าที่เจาะจงต่ำกว่า
  ในตัว
  
  hidden
  ซึ่งอาจทำให้คุณประหลาดใจหากคุณต้องการตั้งค่า hidden
  ในเอลิเมนต์เพื่อแสดงผล display: none นอกจากนี้
  เป็นรูปแบบ display เริ่มต้น เพิ่มการสนับสนุนสำหรับ hidden
  ด้วย :host([hidden]) { display: none }
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
แอตทริบิวต์และพร็อพเพอร์ตี้
  
    
      
        
  อย่าลบล้างแอตทริบิวต์ร่วมที่ผู้เขียนตั้งไว้
        
       | 
    
    
      | เพราะเหตุใด | 
      
  แอตทริบิวต์ร่วมคือแอตทริบิวต์ที่มีอยู่ในองค์ประกอบ HTML ทั้งหมด ใช้บ้าง
  เช่น tabindex และ role องค์ประกอบที่กำหนดเอง
  อาจต้องการตั้งค่า tabindex เริ่มต้นให้เป็น 0 เพื่อให้เป็นแป้นพิมพ์
  โฟกัสได้ แต่คุณควรตรวจสอบก่อนเสมอเพื่อดูว่านักพัฒนาที่ใช้
  องค์ประกอบตั้งค่าเป็นค่าอื่น เช่น หากการตั้งค่า
  tabindex ต่อ -1 นั่นเป็นสัญญาณว่าไม่ต้องการ
  เป็นแบบอินเทอร์แอกทีฟ
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox> ซึ่งอธิบายเพิ่มเติมใน
  อย่าลบล้างผู้เขียนหน้าเว็บ
       | 
    
  
  
    
      
        
  ยอมรับข้อมูลพื้นฐาน (สตริง ตัวเลข บูลีน) เป็นแอตทริบิวต์อย่างใดอย่างหนึ่งเสมอ
  หรือเว็บไซต์
        
       | 
    
    
      | เพราะเหตุใด | 
      
  องค์ประกอบที่กำหนดเอง เช่น องค์ประกอบที่มีมาในตัว ควรสามารถกำหนดค่าได้
  สามารถส่งการกำหนดค่าได้แบบประกาศ ผ่านแอตทริบิวต์ หรือส่ง
  ผ่านพร็อพเพอร์ตี้ JavaScript โดยหลักการแล้ว แอตทริบิวต์ทุกรายการควรลิงก์กับ
  พร็อพเพอร์ตี้ที่เกี่ยวข้อง
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
  
    
      
        
  พยายามซิงค์แอตทริบิวต์และพร็อพเพอร์ตี้ข้อมูลแบบดั้งเดิม โดยจะแสดงข้อมูลจาก
  พร็อพเพอร์ตี้เป็นแอตทริบิวต์ และในทางกลับกันด้วย
        
       | 
    
    
      | เพราะเหตุใด | 
      
  คุณไม่มีทางทราบว่าผู้ใช้จะโต้ตอบกับองค์ประกอบของคุณอย่างไร โดยอาจ
  ตั้งค่าพร็อพเพอร์ตี้ใน JavaScript จากนั้นก็จะอ่านค่านั้น
  โดยใช้ API เช่น getAttribute() หากทุกแอตทริบิวต์มี
  ที่สอดคล้องกันและทั้งสองแบบ จะช่วยให้คุณสามารถ
  ทำงานกับองค์ประกอบของคุณได้ กล่าวคือ การโทร
  setAttribute('foo', value) ควรตั้งค่า
  foo พร็อพเพอร์ตี้และในทางกลับกันด้วย แต่แน่นอนว่ามีข้อยกเว้น
  ด้วยกฎนี้ คุณไม่ควรแสดงพร็อพเพอร์ตี้ความถี่สูง เช่น
  currentTime ในวิดีโอเพลเยอร์ โปรดใช้วิจารณญาณที่ดีที่สุด หาก
  ดูเหมือนว่าผู้ใช้จะโต้ตอบกับพร็อพเพอร์ตี้หรือแอตทริบิวต์ และ
  การสะท้อนความคิดนั้นไม่ใช่เรื่องยุ่งยาก ดังนั้น การทำเช่นนั้นจึงไม่ใช่เรื่องยุ่งยาก
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox> ซึ่งอธิบายเพิ่มเติมใน
  หลีกเลี่ยงปัญหาการใช้งานซ้ำ
       | 
    
  
  
    
      
        
  พยายามยอมรับเฉพาะข้อมูลแบบสมบูรณ์ (ออบเจ็กต์ อาร์เรย์) เป็นพร็อพเพอร์ตี้
        
       | 
    
    
      | เพราะเหตุใด | 
      
  กล่าวโดยทั่วไปคือ ไม่มีตัวอย่างองค์ประกอบ HTML ในตัวที่
  ยอมรับข้อมูลสมบูรณ์ (ออบเจ็กต์และอาร์เรย์ JavaScript ธรรมดา) ผ่าน
   แต่จะยอมรับข้อมูลแบบสมบูรณ์แทนผ่านการเรียกเมธอดหรือ
  พร็อพเพอร์ตี้ มีข้อเสียที่เห็นได้ชัดอยู่ 2-3 ข้อในการยอมรับข้อมูลอย่างละเอียด
  แอตทริบิวต์: การจัดชุดวัตถุขนาดใหญ่ไปยังสตริงอาจมีค่าใช้จ่ายสูง และ
  การอ้างอิงออบเจ็กต์จะหายไปในกระบวนการกำหนดสตริงนี้ สำหรับ
  ตัวอย่างเช่น หากคุณกำหนดเป็นสตริงให้กับออบเจ็กต์ที่มีการอ้างอิงไปยังออบเจ็กต์อื่น
  หรือโหนด DOM การอ้างอิงเหล่านั้นจะหายไป
       | 
    
  
  
    
      
        
  ไม่แสดงพร็อพเพอร์ตี้ข้อมูลแบบสมบูรณ์ในแอตทริบิวต์
        
       | 
    
    
      | เพราะเหตุใด | 
      
  การใช้คุณสมบัติข้อมูลอย่างละเอียดกับแอตทริบิวต์นั้นมีค่าใช้จ่ายสูงโดยไม่จำเป็น
  ต้องมีการทำให้เป็นอนุกรมและดีซีเรียลไลซ์ออบเจ็กต์ JavaScript เดียวกัน ยกเว้น
  คุณมีกรณีการใช้งานที่ตอบได้ด้วยฟีเจอร์นี้เท่านั้น
  ที่ควรหลีกเลี่ยง
       | 
    
  
  
    
      
        
  ลองตรวจหาพร็อพเพอร์ตี้ที่อาจตั้งค่าไว้ก่อนหน้าองค์ประกอบ
  อัปเกรดแล้ว
        
       | 
    
    
      | เพราะเหตุใด | 
      
  นักพัฒนาซอฟต์แวร์ที่ใช้องค์ประกอบของคุณอาจพยายามตั้งค่าพร็อพเพอร์ตี้ในองค์ประกอบ
  ก่อนที่จะมีการโหลดคำจำกัดความ โดยเฉพาะอย่างยิ่งหาก
  นักพัฒนาซอฟต์แวร์ใช้เฟรมเวิร์กที่จัดการคอมโพเนนต์การโหลดและประทับตราองค์ประกอบ
  กับหน้า และเชื่อมโยงพร็อพเพอร์ตี้กับโมเดล
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox> อธิบายเพิ่มเติมใน
  ทำให้พร็อพเพอร์ตี้เป็นแบบ Lazy Loading
       | 
    
  
  
    
      
        
  ห้ามใช้ชั้นเรียนด้วยตนเอง
        
       | 
    
    
      | เพราะเหตุใด | 
      
  องค์ประกอบที่ต้องแสดงสถานะของตัวเองควรดำเนินการดังกล่าวโดยใช้แอตทริบิวต์ 
  โดยทั่วไปจะถือว่าแอตทริบิวต์ class เป็นของ
  นักพัฒนาซอฟต์แวร์ที่ใช้องค์ประกอบของคุณ และการเขียนถึงด้วยตนเองโดยไม่เจตนา
  กระทืบเท้าที่ชั้นเรียนของนักพัฒนาซอฟต์แวร์
       | 
    
  
กิจกรรม
  
    
      
        
  ส่งเหตุการณ์เพื่อตอบสนองต่อกิจกรรมของคอมโพเนนต์ภายใน
        
       | 
    
    
      | เพราะเหตุใด | 
      
  คอมโพเนนต์อาจมีคุณสมบัติที่เปลี่ยนไปตามกิจกรรมที่
  มีแค่คอมโพเนนต์ที่ทราบ เช่น ถ้าตัวจับเวลาหรือภาพเคลื่อนไหว
  หรือทรัพยากรโหลดเสร็จแล้ว การเผยแพร่กิจกรรมจะช่วยได้
  ตอบสนองต่อการเปลี่ยนแปลงเหล่านี้เพื่อแจ้งโฮสต์ว่าสถานะของคอมโพเนนต์คือ
  แตกต่างกัน
       | 
    
  
  
    
      
        
  อย่าส่งเหตุการณ์ตามการตั้งค่าพร็อพเพอร์ตี้ของโฮสต์ (ลงด้านล่าง)
  โฟลว์ข้อมูล)
        
       | 
    
    
      | เพราะเหตุใด | 
      
  การส่งเหตุการณ์เพื่อตอบสนองต่อการตั้งค่าโฮสต์นั้นถือเป็นสิ่งที่ไม่จำเป็น
  (โฮสต์ทราบสถานะปัจจุบันของเนื่องจากเพิ่งตั้งค่า) การส่งกิจกรรม
  ในการตอบกลับการตั้งค่าโฮสต์ พร็อพเพอร์ตี้อาจทําให้เกิดการวนซ้ำกับข้อมูลที่ไม่สิ้นสุด
  ระบบการผูก
       | 
    
    
      | ตัวอย่าง | 
      
  
  <howto-checkbox>
       | 
    
  
วิดีโออธิบาย
อย่าลบล้างผู้เขียนหน้าเว็บ
เป็นไปได้ว่านักพัฒนาซอฟต์แวร์ที่ใช้เอลิเมนต์ของคุณอาจต้องการลบล้าง
สถานะเริ่มต้น ตัวอย่างเช่น การเปลี่ยน ARIA role หรือความสามารถในการโฟกัสด้วย
tabindex ตรวจสอบว่ามีการตั้งค่าเหล่านี้และแอตทริบิวต์ร่วมอื่นๆ หรือไม่
ก่อนที่จะนำค่าของคุณเองไปใช้
connectedCallback() {
  if (!this.hasAttribute('role'))
    this.setAttribute('role', 'checkbox');
  if (!this.hasAttribute('tabindex'))
    this.setAttribute('tabindex', 0);
ทำให้พร็อพเพอร์ตี้เป็นแบบ Lazy Loading
นักพัฒนาซอฟต์แวร์อาจพยายามตั้งค่าพร็อพเพอร์ตี้ในองค์ประกอบก่อน
โหลดคำจำกัดความแล้ว โดยเฉพาะอย่างยิ่งหากนักพัฒนาแอปใช้
เฟรมเวิร์กที่จัดการคอมโพเนนต์การโหลด การแทรกโค้ดลงในหน้า และ
ก็เชื่อมโยงพร็อพเพอร์ตี้กับโมเดล
ในตัวอย่างต่อไปนี้ Angular จะเชื่อมโยง
isChecked เป็นพร็อพเพอร์ตี้ checked ของช่องทำเครื่องหมาย หากคำจำกัดความของ
มีการโหลดช่องทำเครื่องหมายวิธีการแบบ Lazy Loading แล้ว Angular อาจพยายามตั้งค่า
พร็อพเพอร์ตี้ที่ทำเครื่องหมายก่อนที่องค์ประกอบจะอัปเกรด
<howto-checkbox [checked]="defaults.isChecked"></howto-checkbox>
องค์ประกอบที่กำหนดเองควรจัดการสถานการณ์นี้ได้ โดยตรวจสอบว่ามีพร็อพเพอร์ตี้ใด
ได้รับการตั้งค่าในอินสแตนซ์แล้ว <howto-checkbox>
แสดงรูปแบบนี้โดยใช้วิธีการที่เรียกว่า _upgradeProperty()
connectedCallback() {
  ...
  this._upgradeProperty('checked');
}
_upgradeProperty(prop) {
  if (this.hasOwnProperty(prop)) {
    let value = this[prop];
    delete this[prop];
    this[prop] = value;
  }
}
_upgradeProperty() จะบันทึกค่าจากอินสแตนซ์ที่ไม่ได้อัปเกรดและลบ
พร็อพเพอร์ตี้ เพื่อไม่ให้เป็นเงาของตัวตั้งค่าพร็อพเพอร์ตี้ขององค์ประกอบที่กำหนดเอง
วิธีนี้จะทำให้เมื่อคำจำกัดความขององค์ประกอบโหลดในที่สุด ก็จะสามารถ
เพื่อแสดงสถานะที่ถูกต้อง
หลีกเลี่ยงปัญหาเกี่ยวกับการเข้าชมซ้ำ
อยากใช้ attributeChangedCallback() เพื่อแสดงสถานะต่อ
พร็อพเพอร์ตี้ที่สำคัญ เช่น
// When the [checked] attribute changes, set the checked property to match.
attributeChangedCallback(name, oldValue, newValue) {
  if (name === 'checked')
    this.checked = newValue;
}
แต่วิธีนี้สามารถสร้างการวนซ้ำที่ไม่สิ้นสุดได้หากตัวตั้งค่าคุณสมบัติสะท้อนให้เห็นถึง
แอตทริบิวต์
set checked(value) {
  const isChecked = Boolean(value);
  if (isChecked)
    // OOPS! This will cause an infinite loop because it triggers the
    // attributeChangedCallback() which then sets this property again.
    this.setAttribute('checked', '');
  else
    this.removeAttribute('checked');
}
อีกวิธีหนึ่งคืออนุญาตให้ตัวตั้งค่าพร็อพเพอร์ตี้แสดงผลต่อแอตทริบิวต์ และ
ให้ Getter กำหนดค่าตามแอตทริบิวต์
set checked(value) {
  const isChecked = Boolean(value);
  if (isChecked)
    this.setAttribute('checked', '');
  else
    this.removeAttribute('checked');
}
get checked() {
  return this.hasAttribute('checked');
}
ในตัวอย่างนี้ การเพิ่มหรือนำแอตทริบิวต์ออกจะเป็นการตั้งค่าพร็อพเพอร์ตี้ด้วย
สุดท้าย คุณใช้ attributeChangedCallback() เพื่อจัดการผลข้างเคียงได้
เช่น ใช้สถานะ ARIA
attributeChangedCallback(name, oldValue, newValue) {
  const hasValue = newValue !== null;
  switch (name) {
    case 'checked':
      // Note the attributeChangedCallback is only handling the *side effects*
      // of setting the attribute.
      this.setAttribute('aria-checked', hasValue);
      break;
    ...
  }
}