องค์ประกอบของเว็บ HTML ไม่ใช้สไตล์ DOM เงา
ฉันได้สร้างองค์ประกอบเว็บวานิลลาหรือองค์ประกอบ HTML แล้ว เพียงแค่แสดงลิงก์สองลิงก์
ในการห่อหุ้มสิ่งนั้นฉันใช้ shadow DOM อย่างไรก็ตามดูเหมือนว่าจะไม่มีการห่อหุ้ม ในต้นไม้ DOM มันอยู่ใน # shadow-root ซึ่งเป็นสิ่งที่ดี
เหตุใดส่วนประกอบของเว็บจึงใช้สไตล์ส่วนกลางแทนสไตล์ที่ฉันให้ไว้ในเทมเพลตสำหรับส่วนประกอบเว็บของฉัน
ข้อความเป็นสีแดงและคาดว่าจะเป็นสีเขียว
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
คำตอบ
แม้ว่าคำถามนี้จะมีคำตอบที่ยอมรับแล้ว แต่การย้ายลูกของสล็อตไปที่ shadowRoot นั้นไม่เป็นที่ต้องการสำหรับกรณีการใช้งานส่วนใหญ่
สิ่งที่คุณอาจต้องทำคือใช้::slotted()
ตัวเลือก
เพียงจำไว้ว่าสไตล์ที่ใช้กับลูกของสล็อตผ่าน::slotted()
ตัวเลือกจะทำหน้าที่เป็นสไตล์ "ค่าเริ่มต้น" เท่านั้นและยังสามารถแทนที่ได้โดยใช้สไตล์ใน DOM ที่มีแสง
ตัวอย่างเช่นตรวจสอบเวอร์ชันแก้ไขของข้อมูลโค้ดของคุณ:
อย่างที่คุณเห็นคราวนี้my-el
พยายามใช้ทั้งสีและสไตล์การตกแต่งข้อความเพื่อยึด ( <a>
) ลูก ๆ ในช่องใดก็ได้
อย่างไรก็ตามในไลท์ดอมเรามีa.special
ตัวเลือกที่แทนที่สีดังนั้น<a class="special">
จะเป็นสีแดงไม่ใช่สีเขียว
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
::slotted(a) {
color: green;
text-decoration: none;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a.special {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a class="special" href="example.com">Item2</a>
</my-el>
คำอธิบายโดยละเอียดทั้งหมดอยู่ใน:: ตัวเลือก CSS แบบ slotted สำหรับลูกที่ซ้อนกันในสล็อต shadowDOM
TL; ดร
ลิงก์ของคุณอยู่ใน lightDOM ดังนั้นจึงมีสไตล์โดย DOM (ในรหัสของคุณคือเอกสาร DOM)
การย้ายโหนดจาก lightDOM ไปยัง shadowDOM เป็น "โซลูชัน" อย่างหนึ่ง แต่คุณไม่ได้ใช้สล็อตแล้ว
FYI รหัสของคุณสามารถบีบอัดเป็น:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
คำตอบที่เกี่ยวข้องกับ SLOT เพิ่มเติมสามารถพบได้ใน StackOverflow Search: Custom Elements SLOTs
สังเกตบรรทัดนี้คุณต้องย้าย / คัดลอกองค์ประกอบไปที่เงาเช่น:
this.shadow.innerHTML = this.innerHTML + template;
ฉันได้เพิ่มสิ่งนี้เพื่อแสดงให้เห็นว่าสไตล์อินไลน์เท่านั้นที่จะถูกนำไปใช้กับองค์ประกอบ Shadow Dom .. ดังนั้นลิงก์ที่คัดลอกใน SD จึงใช้สไตล์ของคุณ :)
เพื่อให้สีแดงจะเป็นGLOBAL
, สีเขียวจะเป็นSHADOW
องค์ประกอบ
class MyEl extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.shadow = this.attachShadow({ mode: "open" });
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = this.innerHTML + template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>