UNPKG

joicomponents

Version:

Design patterns to build native web components

129 lines (124 loc) 4.28 kB
<script> class PortraitFrame extends HTMLElement { constructor() { super(); this.attachShadow({mode: "open"}); this.shadowRoot.innerHTML = ` <style> :host(*){ border: 10px solid darkgreen; width: 300px; height: 300px; display: block; } green-frame { box-sizing: border-box; display: block; width: 100%; height: 100%; } </style> <green-frame id="frameOne"> <slot id="outer">a picture</slot> </green-frame>`; } } class GreenFrame extends HTMLElement { constructor() { super(); this.attachShadow({mode: "open"}); this.shadowRoot.innerHTML = ` <style> :host { border: 4px solid green; } </style> <slot id="inner"></slot>`; this.shadowRoot.addEventListener("slotchange", function (e) { console.log(e.composedPath(), e.target.assignedNodes(), e.target.assignedNodes({flatten: true})); }); } } customElements.define("green-frame", GreenFrame); customElements.define("portrait-frame", PortraitFrame); </script> <style> pre { margin: 0 } </style> <script> document.addEventListener("DOMContentLoaded", function () { const pf = document.createElement("portrait-frame");//slotchange event document.querySelector("body").appendChild(pf); let pre = document.createElement("pre"); pre.innerText = "¯\\_(ツ)_/¯"; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " | | "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " | 6 | "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " === "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " | | "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " | | | "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " | | | "; pf.appendChild(pre); //slotchange event pre = document.createElement("pre"); pre.innerText = " ^ ^ "; pf.appendChild(pre); //slotchange event }); </script> <h3>SlotchangeExplosion #3</h3> <p> When we view this situation from HTML, it looks the same as in our previous example SlotchangeExplosion #1. The only difference is that two empty scripts will be processed along the way. But, in your console, you should now see 4 (or more) logs. Why is that? </p> <p> The first script deliberately causes the browser to break its creation of the DOM. This means that the browser will make a "temporary" DOM branch that looks like this: <pre> ... < portrait-frame > #shadowRoot .. < green-frame > #shadowRoot < slot#inner > < slot#outer > < pre >¯\_(ツ)_/¯ < pre > | | ---break 1--- </pre> This is the temporary state of the DOM in which the second slotchange event is dispatched. And you can see this state in the slot#outer.assignedElements({flatten: true}) which is: `[pre, pre, pre, script]` </p> <p> The second script does the same with a "temporary" DOM branch that looks like this: <pre> ... < portrait-frame > #shadowRoot .. < green-frame > #shadowRoot < slot#inner > < slot#outer > < pre >¯\_(ツ)_/¯ < pre > | | < pre > | 6 | ---break 2--- </pre> This is the temporary state of the DOM in which the third slotchange event is dispatched. And you can see this state in the slot#outer.assignedElements({flatten: true}) which is: `[pre, pre, pre, script, pre, script]` </p> <p> The last slotchange event occurs when the DOM branch is complete. : </p>