ในการทำงานประจำวัน เมื่อเรากำหนด Component เราต้องพิจารณาถึง การห่อหุ้ม ของมัน กล่าวคือ คุณคาดหวังให้สไตล์ที่กำหนดไว้ใน Component นี้มีผลเฉพาะกับ Component นี้เท่านั้น หรือคุณต้องการให้มันดำเนินการทั่วโลก ใน Angular รูปแบบของส่วนประกอบสามารถห่อหุ้มไว้ภายในองค์ประกอบโฮสต์ของส่วนประกอบได้ เพื่อไม่ให้ส่งผลกระทบต่อส่วนที่เหลือของแอปพลิเคชัน มัณฑนากรส่วนประกอบมีตัวเลือกการห่อหุ้มที่สามารถใช้เพื่อควบคุมวิธีการใช้การห่อหุ้มมุมมองแบบรายส่วนประกอบ [คำแนะนำเกี่ยวกับบทช่วยสอนที่เกี่ยวข้อง: "บทช่วยสอนเชิงมุม"]
มีโหมดการห่อหุ้มสามโหมดใน Angular ได้แก่ ViewEncapsulation.ShadowDom, ViewEncapsulation.Emulated และ ViewEncapsulation.None
ส่งออก Enum ViewEncapsulation { - * จำลองพฤติกรรมการห่อหุ้ม Shadow DOM ดั้งเดิมโดยการเพิ่มคุณลักษณะเฉพาะให้กับ องค์ประกอบโฮสต์ของคอมโพเนนต์ * และใช้แอตทริบิวต์เดียวกันกับตัวเลือก CSS ทั้งหมดที่มีให้ * ผ่าน {@link Component#styles styles} หรือ {@link Component#styleUrls styleUrls} - * นี่คือตัวเลือกเริ่มต้น - จำลอง = 0, - * ไม่มีการห่อหุ้มสไตล์ CSS ใดๆ ซึ่งหมายความว่าทุกสไตล์ที่มีให้ * ผ่าน {@link Component#styles styles} หรือ {@link Component#styleUrls styleUrls} มีผลบังคับใช้ * ไปยังองค์ประกอบ HTML ใด ๆ ของแอปพลิเคชันโดยไม่คำนึงถึงคอมโพเนนต์โฮสต์ - ไม่มี = 2, - * ใช้ Shadow DOM API ดั้งเดิมของเบราว์เซอร์เพื่อสรุปสไตล์ CSS ซึ่งหมายความว่ามันสร้างขึ้น * ShadowRoot สำหรับองค์ประกอบโฮสต์ของส่วนประกอบซึ่งจะใช้ในการห่อหุ้ม * สไตล์ของ Component ทั้งหมด - ชาโดว์โดม=3 }
หากไม่ได้ระบุ ค่าจะได้มาจาก CompilerOptions ตัวเลือกคอมไพเลอร์เริ่มต้นคือ ViewEncapsulation.Emulated
หากตั้งค่านโยบายเป็น ViewEncapsulation.Emulated และคอมโพเนนต์ไม่ได้ระบุสไตล์หรือ styleUrls คอมโพเนนต์จะเปลี่ยนเป็น ViewEncapsulation.None โดยอัตโนมัติ
คุณทราบหรือไม่ว่าเหตุใดจึงไม่มี 1 ในประเภทการแจงนับ เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง
นอกเหนือจากการห่อหุ้ม ShadowDom ใน Angular แล้ว ก่อนอื่นเรามาดูกันว่า ShadowDOM คืออะไร
Shadow DOM อนุญาตให้แนบแผนผัง DOM ที่ซ่อนอยู่กับแผนผัง DOM ปกติ โดยเริ่มต้นด้วยโหนดรูทเงา ด้านล่างโหนดรูทนี้อาจเป็นองค์ประกอบใดก็ได้ เช่นเดียวกับองค์ประกอบ DOM ทั่วไป
ต่อไปนี้เป็นคำศัพท์เฉพาะของ Shadow DOM ที่เราต้องทำความเข้าใจ:
คุณสามารถจัดการ Shadow DOM ได้ในลักษณะเดียวกับ DOM ทั่วไป เช่น การเพิ่มโหนดลูก การตั้งค่าคุณสมบัติ และการเพิ่มสไตล์ของคุณเองให้กับโหนด (เช่น ผ่านคุณสมบัติ element.style) หรือการเพิ่มสไตล์ให้กับทั้งหมด Shadow DOM (เช่น การเพิ่มสไตล์ภายในองค์ประกอบ) ความแตกต่างก็คือองค์ประกอบภายใน Shadow DOM จะไม่ส่งผลกระทบต่อองค์ประกอบภายนอก (ยกเว้น :focus-within) ซึ่งอำนวยความสะดวกในการห่อหุ้ม
ลองดูตัวอย่างง่ายๆ
<!DOCTYPE html> <html> <หัว> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, Initial-scale=1.0"> <title>เงา DOM</title> <สไตล์> ช่วง{ สี: สีเขียว; - </สไตล์> </หัว> <ร่างกาย> <span>ฉันคือรูท</span> <div id="แอป"></div> <สคริปต์> ให้ app = document.querySelector('#app'); ให้ shadow1 = app.attachShadow({ mode: 'open'}); ให้ style1 = document.createElement('style'); style1.appendChild(document.createTextNode("span{สี: สีแดง;}")); shadow1.appendChild(style1); ให้ span1 = document.createElement('span'); span1.textContent = 'ฉันเป็นสแปน'; shadow1.appendChild (span1); </สคริปต์> </ร่างกาย> </html>
ตัวอย่างข้างต้นกำหนดสไตล์สแปนสากลและสไตล์สแปนใน shadowDOM จะเห็นได้ว่าไม่ได้รับผลกระทบซึ่งกันและกัน
หลังจากทำความเข้าใจว่า ShadowDOM คืออะไรแล้ว เรามาดูการห่อหุ้มของ ShadowDOM ในเชิงมุมกันดีกว่า
Angular ใช้ Shadow DOM API ในตัวของเบราว์เซอร์เพื่อรวมมุมมองของส่วนประกอบใน ShadowRoot (ซึ่งทำหน้าที่เป็นองค์ประกอบโฮสต์ของส่วนประกอบ) และใช้สไตล์ที่ให้มาในลักษณะแยกส่วน ViewEncapsulation.ShadowDom ใช้งานได้เฉพาะในเบราว์เซอร์ที่รองรับ Shadow DOM ในตัวเท่านั้น ไม่ใช่ทุกเบราว์เซอร์ที่รองรับ ด้วยเหตุนี้ ViewEncapsulation.Emulated จึงเป็นโหมดที่แนะนำและเป็นโหมดเริ่มต้น
ตัวอย่างเช่น ในตัวอย่างต่อไปนี้ ให้ใช้ ViewEncapsulation.ShadowDom
@ส่วนประกอบ({ ตัวเลือก: 'ผู้ใช้ลูก' templateUrl: 'UserChild.component.html', สไตล์: [` h3{ สี: สีแดง; - - การห่อหุ้ม: ViewEncapsulation.ShadowDom - คลาสส่งออก UserChildComponent ใช้ OnInit { - -
จากหน้าที่รันอยู่ เราจะเห็นว่าคอมโพเนนต์ user-child ถูกห่อหุ้มภายในเป็น ShadowDOM และสไตล์ก็ถูกห่อหุ้มไว้ด้านในด้วย ซึ่งจะไม่ส่งผลกระทบต่อสไตล์ภายนอก
Angular ปรับเปลี่ยนตัวเลือก CSS ของส่วนประกอบเพื่อให้ใช้กับมุมมองของส่วนประกอบเท่านั้น และไม่ส่งผลกระทบต่อองค์ประกอบอื่น ๆ ในแอปพลิเคชัน (จำลองพฤติกรรม Shadow DOM)
เมื่อใช้การห่อหุ้มมุมมองจำลอง Angular จะประมวลผลสไตล์ส่วนประกอบทั้งหมดล่วงหน้าเพื่อให้ใช้กับมุมมองของส่วนประกอบเท่านั้น ใน DOM ของแอปพลิเคชัน Angular ที่รันอยู่ องค์ประกอบที่มีส่วนประกอบที่ใช้รูปแบบการห่อหุ้มมุมมองจำลองจะมีแอตทริบิวต์เพิ่มเติมที่แนบมาด้วย:
<hero-details _nghost-pmm-5> <h3 _ngcontent-pmm-5>มิสเตอร์แฟนทาสติก</h3> <ฮีโร่ทีม _ngcontent-pmm-5 _nghost-pmm-6> <h4 _ngcontent-pmm-6>ทีม</h4> </ฮีโร่ทีม> </hero-details>
มีคุณลักษณะดังกล่าวอยู่สองประการ:
คุณลักษณะ | detail_nghost |
---|---|
จะ | ถูกเพิ่มไปยังองค์ประกอบที่ล้อมรอบมุมมองส่วนประกอบ ซึ่งจะเป็น ShadowRoots ใน Shadow DOM wrapper ดั้งเดิม โดยปกติจะเป็นกรณีนี้กับองค์ประกอบโฮสต์ของส่วนประกอบ |
_ngcontent | ถูกเพิ่มให้กับองค์ประกอบย่อยในมุมมองส่วนประกอบ และแอตทริบิวต์เหล่านี้ใช้เพื่อจับคู่องค์ประกอบกับ ShadowRoots จำลองตามลำดับ (องค์ประกอบโฮสต์ที่มีแอตทริบิวต์ _nghost ที่ตรงกัน) |
ค่าที่แน่นอนของคุณสมบัติเหล่านี้เป็นรายละเอียดการใช้งานส่วนตัวของ Angular สร้างขึ้นโดยอัตโนมัติและคุณไม่ควรอ้างอิงในรหัสแอปพลิเคชันของคุณ
พวกเขากำหนดเป้าหมายสไตล์ส่วนประกอบที่สร้างขึ้นซึ่งถูกแทรกเข้าไปในส่วนต่างๆ ของ DOM:
[_nghost-pmm-5] { จอแสดงผล: บล็อก; เส้นขอบ: 1px สีดำทึบ; - h4[_ngcontent-pmm-6] { สีพื้นหลัง: สีขาว; เส้นขอบ: 1px ทึบ #777; }
สไตล์เหล่านี้ได้รับการประมวลผลภายหลัง ดังนั้นตัวเลือก CSS แต่ละตัวจึงได้รับการเสริมด้วยแอตทริบิวต์ _nghost หรือ _ngcontent ที่เหมาะสม ตัวเลือกที่ปรับเปลี่ยนเหล่านี้ช่วยให้มั่นใจได้ว่าสไตล์จะถูกนำไปใช้กับมุมมองของส่วนประกอบในลักษณะที่แยกจากกันและเป็นเป้าหมาย
<p>เด็กได้ผล!</p>
p{ สี: สีเขียว; }
@ส่วนประกอบ({ ตัวเลือก: 'แอปลูก' templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], การห่อหุ้ม: ViewEncapsulation.Emulated - คลาสส่งออก ChildComponent ใช้ OnInit { - -
ผลลัพธ์ของการตั้งค่า ViewEncapsulation.Emulated คือไม่มี Shadow DOM แต่ส่วนประกอบถูกห่อหุ้มผ่านกลไกการบรรจุรูปแบบที่ Angular มอบให้ เพื่อให้รูปแบบของส่วนประกอบไม่ได้รับผลกระทบจากอิทธิพลภายนอก แม้ว่าสไตล์จะยังคงใช้กับเอกสารทั้งหมด แต่ Angular จะสร้างตัวเลือก [_ngcontent-oow-c11] สำหรับ p จะเห็นได้ว่าสไตล์ที่เรากำหนดไว้สำหรับส่วนประกอบนั้นได้รับการแก้ไขโดย Angular พูดง่ายๆ ก็คือ แม้ว่าจะเป็นสไตล์สากล แต่ก็จะไม่ส่งผลกระทบต่อสไตล์ของส่วนประกอบอื่นๆ เนื่องจากตัวเลือกอัตโนมัติ หากคุณเพิ่มแอตทริบิวต์นี้ให้กับองค์ประกอบอื่นๆ ด้วยตนเอง สไตล์ก็จะนำไปใช้กับองค์ประกอบนี้ด้วย
Angular ไม่ได้ใช้รูปแบบการห่อหุ้มมุมมองใดๆ ซึ่งหมายความว่าสไตล์ใดๆ ที่ระบุสำหรับส่วนประกอบนั้นจะถูกนำไปใช้ทั่วโลกจริงๆ และอาจส่งผลต่อองค์ประกอบ HTML ใดๆ ที่มีอยู่ในแอปพลิเคชัน รูปแบบนี้โดยพื้นฐานแล้วจะเหมือนกับการเพิ่มสไตล์ใน HTML เอง
parent:
<p #caption>ผู้ปกครองใช้งานได้!{{count}}</p> <p #caption>อันแรก: {{count}}</p> <span class="red-font">ผู้ปกครอง</span> <app-child></app-child>
ลูก:
<div style="border: 1px solid green;"> <p>เด็กได้ผล!</p> <span class="red-font">เด็ก</span> </div>
พี{ สี: สีเขียว; - .red แบบอักษร { สี: สีแดง; }
@ส่วนประกอบ({ ตัวเลือก: 'แอปลูก' templateUrl: './child.component.html', styleUrls: ['./child.component.scss'], การห่อหุ้ม: ViewEncapsulation ไม่มี - คลาสส่งออก ChildComponent ใช้ OnInit { - -
ใน Angular2
@ส่วนประกอบ({ - การห่อหุ้ม: ViewEncapsulation.Native - ส่งออกคลาส UserComponent {
การตั้งค่า ViewEncapsulation.Native ส่งผลให้ใช้คุณลักษณะ Shadow DOM ดั้งเดิม Angular จะแสดงส่วนประกอบตามรูปแบบ Shadow DOM ที่เบราว์เซอร์รองรับ อันที่จริงนี่คือ ViewEncapsulation.ShadowDom รุ่นหลัง
เราได้แนะนำวิธีการห่อหุ้มมุมมองเชิงมุมสามวิธีและคุณลักษณะตามลำดับ ในการทำงานประจำวัน คุณควรเลือกวิธีการห่อหุ้มแบบใดตามสถานการณ์เฉพาะ