admin管理员组文章数量:1317915
I have a web ponent like this
<template id="ponent">
<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#ponent').content;
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.cloneNode(true));
// executeThis() when all scripts have been loaded
}
},
});
document.registerElement('react-webponent', { 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 ponents?
I have a web ponent like this
<template id="ponent">
<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#ponent').content;
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.cloneNode(true));
// executeThis() when all scripts have been loaded
}
},
});
document.registerElement('react-webponent', { 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 ponents?
Share Improve this question edited Aug 7, 2017 at 11:28 Lukas asked Aug 7, 2017 at 11:07 LukasLukas 10.4k17 gold badges82 silver badges128 bronze badges 11- You can do that very easily if you are using JQuery. – Koby Douek Commented Aug 7, 2017 at 11:09
- Sorry, but I don't want to load jQuery just for this little thing – Lukas Commented Aug 7, 2017 at 11:10
- Possible duplicate of pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it – Koby Douek Commented Aug 7, 2017 at 11:27
- Might be, but will it work for web ponents? – Lukas Commented Aug 7, 2017 at 11:28
- 3 Using the load event (or onload event handler, or the onload element attribute) on script is the best solution. – Supersharp Commented Aug 7, 2017 at 12:28
2 Answers
Reset to default 2Your update example is the best way I know of.
I had a similar issue looking to prevent FOUC on my ponents 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 pare 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 ponent 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 posed : true
to the event args.
var event = new CustomEvent('load', {bubbles : true, posed : true});
shadowRoot.dispatchEvent(event);
From what I understand, as of now,
you do not have event listeners for
onload
of the dom in your shadow rootwhen you define a custom element, you can have a
connectedCallback
which is called when you attach an element to your DOM
from what you are trying, it seems to me, that you are trying to ascertain, the exact time when your shadow DOM loads its internal scripts
from what I know, scripts are not scoped to your element, and are global.
So Instead of trying to do what you are doing at the moment which is,
- querying the shadow Root's DOM structure, collecting the script tags and attaching an onload,
you can simply slap an onload to the tags which work like they always have.
Further, you might be interested in mutation observers
if you may want to observe for changes to your shadow DOM, once it is attached
and beyond.
AFAIK, you can not observe DOM changes while you are constructing your element itself / before it is attached
Or, if you are defining your elements in a different file and prefer using HTML Imports
to import them onto the document,
you can use the webponentsready
listener from the document that imports, which fires when all the DOM is imported, parsed, and loaded
If there is indeed a way to observe the DOM or listen to template attachments to your element, I would also like to know.
Also, Since you are trying to embed your react app into the custom element, which is probably why you had this question of knowing when to call the loadreactapp
function, you may want to consider using slots
in your shadow DOM, which open up places where you may distribute content after your element has been registered on the browser
Just add your apps or other custom elements, by passing in the attribute slot=<slotname>
本文标签: javascriptEvent when web component has loadedStack Overflow
版权声明:本文标题:javascript - Event when web component has loaded - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742007650a2412283.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论