I have a web component like this
<template id="component">
<link href="/static/css/main.cacbacc7.css" rel="stylesheet">
<script src="/static/js/vendor.js" type="text/javascript"></script>
<script src="/static/js/bundle.js" type="text/javascript"></script>
<span id="react-app"></span>
</template>
<script>
(function (window, document) {
const doc = (document._currentScript || document.currentScript).ownerDocument;
const proto = Object.create(HTMLElement.prototype, {
attachedCallback: {
value: function () {
const template = doc.querySelector('template#component').content;
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.cloneNode(true));
// executeThis() when all scripts have been loaded
}
},
});
document.registerElement('react-webcomponent', { prototype: proto });
})(window, document);
</script>
Can I know when all script
tags in my template
have been loaded?
Update
What I am currently doing is
const scripts = [...shadowRoot.querySelectorAll('script')];
let scriptsLoaded = 0;
scripts.forEach(function (script) {
script.addEventListener('load', function () {
if (++scriptsLoaded >= scripts.length) {
LoadReactAppIntoShadowDomContainer(shadowRoot.querySelector('#react-app'));
}
})
});
But I am hoping for a nicer way.
About the possible duplicate: Will it work for web components?
onload. The load event on the window object triggers when the whole page is loaded including styles, images and other resources. This event is available via the onload property.
The onload event occurs when an object has been loaded. onload is most often used within the <body> element to execute a script once a web page has completely loaded all content (including images, script files, CSS files, etc.).
DOMContentLoaded is a great event to use to hookup UI functionality to complex web pages. The DOMContentLoaded event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page).
You can check the document. readyState property. From MDN: Returns "loading" while the document is loading, "interactive" once it is finished parsing but still loading sub-resources, and "complete" once it has loaded.
Your update example is the best way I know of.
I had a similar issue looking to prevent FOUC on my components that were importing CSS via tags.
The only solution I could find is as per your update. QS the ShadowRoot to find the <link>
or <scripts>
, add a load event listener to each and compare the load count.
The one optimisation you might consider, is when the count matches you can dispatch your own custom load event from the shadow root itself, that a listener on your component shadow root (or further up the tree) can handle.
var event = new CustomEvent('load');
shadowRoot.dispatchEvent(event);
If you want it to bubble up and cross the shadow boundary you'll need to add composed : true
to the event args.
var event = new CustomEvent('load', {bubbles : true, composed : true});
shadowRoot.dispatchEvent(event);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With