我们知道css具有全局特性,Shadow DOM 中css不会影响文档的css,也不会使全局css传递到shaDow DOM 的css,就是具有沙箱形式
<style> h1{ color:red; } </style> <app-element></app-element> <span>33233</span> <script> customElements.define("app-element", class App extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.shadowRoot.innerHTML = ` <style> span { background: steelblue; padding: 5px; color: white; } </style> <div> <span>CSS</span> <h1>3333</h1> </div> `; } }); </script> <h1>h1</h1>我们发现,css被完全隔离开了
自定义元素 <app-element></app-element> <script> customElements.define("app-element", class extends HTMLElement { connectedCallback() { this.innerHTML = "<div>Hello, friend!</div>"; } }); </script> 在自定义元素里面插入 shadow DOM <app-element> <div>Contenido previo del elemento</div> </app-element> <script> customElements.define("app-element", class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.shadowRoot.innerHTML = "<div>Hello, friend!</div>"; } }); </script>我们发现创建页面上的Shadow DOM 后,页面上.container 的dom被隐藏了
换句话说当我们附加shadow DOM 时,它将隐藏Light DOM,但是尽管Light DOM 被隐藏了,但是可以通过浏览器查询到代码
<app-element> #shadow-root (open) <div>Hello, friend!</div> <div>Contenido previo del elemento</div> </app-element>我们this.shadowRoot.innerHTML用于修改Shadow DOM。如果使用,我们将this.innerHTML只修改Light DOM。
插槽<slot> 插槽中插入我们放置的Light DOM
connectedCallback() { this.shadowRoot.innerHTML = "<div>Hello, friend! <slot>默认插槽</slot></div>"; }我们发现默认插槽会被填充.container 的内容,当<app-element> 里面为空的话,会填充默认的插槽
命名插槽 <app-element> <h2 slot="name">Manz</h2> <span slot="role">Developer</span> <p slot="description">I hate Internet Explorer.</p> </app-element> <script> customElements.define("app-element", class extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); } connectedCallback() { this.shadowRoot.innerHTML = ` <div> <slot></slot> <slot></slot> <slot></slot> </div> `; } }); </script>通过在外部定义css,修改插槽中的css,通过我们给出<slot></slot>给出一个默认信息
::sloted 伪类 connectedCallback() { this.shadowRoot.innerHTML = ` <style> ::slotted(h2) { color: blue; } </style> <div> <slot></slot> <slot></slot> <slot></slot> </div> `; }会优先考虑全局css,但是如果有!important 会考虑优先级进行替换
正常情况下,全局的css大于自身的
::slotted(h2) { color: blue; } 插槽的事件检测 事件 描述slotchange 当它检测到插槽元素关联已更改时,将触发该事件。
们将像处理任何事件一样使用.addEventListener()该事件,使用有<slot>问题的事件来监听它并检测它何时被触发,并执行关联的功能
const slot = this.shadowRoot.querySelector("slot"); slot.addEventListener("slotchange", () => console.log("¡El slot ha cambiado!"));例子,能监控到变化
element.setAttribute('slot', slotName); // element.assignedSlot = $slot element.removeAttribute('slot'); // element.assignedSlot = null提地写了一个完整的demo,方便理解
<app-element> <button>++</button> <h1>xxxx</h1> </app-element>js部分
class AppElement extends HTMLElement { constructor() { super(); this.attachShadow({mode: "open"}); } slot; connectedCallback() { // 添加到页面上 this.shadowRoot.innerHTML = `<slot></slot>`; // 查找到slot,并且监控属性的变化 this.slot = document.querySelector('app-element').shadowRoot.querySelector('slot'); this.slot.addEventListener('slotchange',e=>{ console.log('触发'); }) } } customElements.define("app-element", AppElement) // 点击的时候修改属性 function add() { let slot = document.querySelector('app-element').shadowRoot.querySelector('slot'); slot.setAttribute('name','333') }