My goal is to create and utilize native web components by defining them as HTML files containing markup, CSS, and Javascript all bundled together in one file, similar to how Vue handles .vue files. These components would be fetched from an external components.html
file and loaded onto a page using fetch().
While I have successfully loaded the HTML and CSS, I am facing an issue with the Javascript not being executed by the browser. Vue requires a build step to 'compile' .vue files, which means there is no live loading of .vue files. However, I aim to achieve live loading. Is this idea unconventional?
Most native web component frameworks define their components entirely in Javascript, but I prefer a more declarative approach using HTML without template literal definitions. My objective is to incorporate methods and potentially data into custom elements upon instantiation. Using eval() doesn't seem like a feasible option, correct?
Although having the Javascript initially inactive prevents global scope pollution, I struggle with reading it and injecting it into the custom element class. How can I make it work so that the script within the component, such as the methods
object, functions properly?
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);
}