joicomponents
Version:
Design patterns to build native web components
93 lines (86 loc) • 2.81 kB
HTML
<script>
function log(e){
console.log(this.tagName, e.target.tagName + "#" + e.target.id);
}
class GrandFather extends HTMLElement {
constructor(){
super();
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = "<the-father><slot id='grandFather'></slot></the-father>";
this.shadowRoot.addEventListener("slotchange", log.bind(this));
}
}
class TheFather extends HTMLElement {
constructor(){
super();
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = "<the-child><slot id='father'></slot></the-child>";
this.shadowRoot.addEventListener("slotchange", log.bind(this));
}
}
class TheChild extends HTMLElement {
constructor(){
super();
this.attachShadow({mode: "open"});
this.shadowRoot.innerHTML = "<slot id='child'></slot>";
this.shadowRoot.addEventListener("slotchange", log.bind(this));
}
}
customElements.define("grand-father", GrandFather);
customElements.define("the-father", TheFather);
customElements.define("the-child", TheChild);
</script>
<grand-father>matroska</grand-father>
<h3>Explanation: </h3>
The flattened DOM looks like this:
<pre>
...
< grand-father >
#shadowRoot
< the-father >
#shadowRoot
< the-child >
#shadowRoot
< slot#child >
< slot#father >
< slot#grandFather >
matroska
</pre>
Constructing this DOM produces six logs:
<pre>
THE-CHILD SLOT#father
THE-FATHER SLOT#father
THE-CHILD SLOT#child
THE-CHILD SLOT#grandFather
THE-FATHER SLOT#grandFather
GRAND-FATHER SLOT#grandFather
</pre>
<ol>
<li>
Log 1 and 2 are the same slotchange event, ie. slot#grandFather being transposed to slot#father.
</li>
<li>
Log 3 is the innermost slotchange event, ie. slot#father being transposed to slot#child.
</li>
<li>
Log 4, 5, and 6 is the final slotchange event, ie. "matroska" being transposed to slot#grandFather.
</li>
<li>
The slotchange listener are triggered: 3 x the-child, 2 x the-father, 1 x grand-father.
the-child web component has principally no way of knowing how many times its slotchange listener
will be triggered during construction.
</li>
</ol>
<pre>
...
< grand-father > _
#shadowRoot *6
< the-father > _ |
#shadowRoot *2 *5
< the-child > | _ |
#shadowRoot *1 *3 *4
< slot#child > | ^ |
< slot#father > ^ |
< slot#grandFather > ^
matroska
</pre>