Web Components โฉ Shadow DOM โฉ Events โฉ
๐ ๅ่ ๐ ็ธ้ ๐ ๆๅ
The events that do cross the shadow boundary are:
blur, focus, focusin, focusout
click, dblclick, mousedown, mouseenter, mousemove, ...
compositionstart, compositionupdate, compositionend
dragstart, drag, dragend, drop, ...
Built-in Events
Custom Events
If composed: false (default), consumers won't be able to listen for the event outside of your shadow root.
1๏ธโฃ js helpers html css
Copy // attach shadow root (โญ๏ธ so outer's light DOM is not shown)
outer.attachShadow({mode: 'open'});
let inner = document.createElement('div');
outer.shadowRoot.append(inner);
/*
div#outer
#shadow-dom
div#inner
*/
// โญ๏ธ listen for 'test' event
document.addEventListener('test', e => log(lightDOM, e.detail));
outer.shadowRoot.addEventListener('test', e => log(shadowDOM, e.detail));
// โญ๏ธ composed custom event
function sendComposedEvent(){
inner.dispatchEvent(new CustomEvent('test', {
bubbles: true,
composed: true, // โญ๏ธ composed
detail: "'composed' event from inner <div>"
}));
}
// โญ๏ธ not composed custom event
function sendNonComposedEvent(){
inner.dispatchEvent(new CustomEvent('test', {
bubbles: true,
composed: false, // โญ๏ธ not composed
detail: "not composed"
}));
}
Copy // โญ๏ธ escape HTML special characters
String.prototype.escapeHTML = function () {
return this
.replace(/&/g, '&' ) // ampersand (must be firstโ๏ธ)
.replace(/>/g, '>' ) // greater than
.replace(/</g, '<' ) // less than
.replace(/"/g, '"') // double-quote
.replace(/'/g, ''' ) // single-quote
.replace(/`/g, '`' ); // backtick
}
// log
function log(dom, msg) {
dom.innerHTML += msg.escapeHTML() + '<br>';
}
Copy <!-- โญ๏ธ element with shadow DOM -->
<div id="outer">outer div</div>
<div id="buttons">
<button onclick="sendComposedEvent()">composed event</button>
<button onclick="sendNonComposedEvent()">non-composed event</button>
</div>
<!-- console log -->
<div id="lightDOM" class="output">
<p>Light DOM event logs:</p>
</div>
<div id="shadowDOM" class="output">
<p>Shadow DOM event logs:</p>
</div>
Copy .output {
border: 1px solid black;
padding: 8px;
background: black;
color: white;
}
.output p {
margin: -8px;
margin-bottom: 8px;
padding: 8px;
background: tomato;
}
#lightDOM p {
background: hsl(225, 80%, 60%);
}
#buttons {
margin-bottom: 8px;
}