So I want to create and use native web components and describe them as HTML files with markup, CSS and Javascript bundled together in one file like how Vue does .vue files. The components would be loaded on a page from an external components.html
file, for example, via fetch().
So far I can load the HTML and CSS without a problem, however the Javascript is "dead", the browser doesn't run it or recognize it. As I understand Vue requires a build step in order to 'compile' .vue files. There is no live loading of .vue. Well, I want to do live loading. Is that silly?
All the native web component 'frameworks' I see out there define their components entirely in Javascript but I want to do it more declaratively with HTML and without template literal HTML definitions. I basically want to have methods and possibly data attached to custom elements when they are instantiated. Also, eval() is not a viable option, right?
I guess it is good that the Javascript initially comes in dead, so it doesn't pollute the global scope. But then how can I read it and basically inject it into the custom element class?
Here is an example of my code, which works fine except for loading the Javascript in the component, since the methods
object does not exist anywhere.
components.html
<template id="my-dog">
<style>
.fur {color: brown}
</style>
<img src="dog.gif" onclick="speak">
<p class="fur">This is a dog</p>
<script>
methods = {
speak(){alert("Woof!");}
}
</script>
</template>
template creation script
//(skipping the part where I fetch components.html)
//(and inject them into the page)
//(and then iterate over each template until...)
templates.forEach(x=>{createTemplate(x)}) //ie. createTemplate('my-dog')
function createTemplate(elementName){
/*various code*/
let elemClass = class extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
}
}
// THIS WORKS! But how can I do the same for speak() function
// and other functions and variables defined in the template?
elemClass.prototype['test'] = ()=>{console.log("This is a test")}
customElements.define(elementName, elemClass);
}