If you haven't read the first article on MVU, I invite you to do so.
Let's continue our adventures with MVU.
This time we will code a very simple counter web component.
Without any ceremony here is the definition of our component.
As you can see, there is very little stuff in it.
class MyCounter extends HTMLElement {
constructor() {
super()
this.state = {
count: Number(this.getAttribute("init")) || 0
}
this.append(myCounter(this))
}
update() {
render(this, myCounter(this))
}
}
customElements.define('my-counter', MyCounter);
In fact the most 'heavy' part is the implementation of the 'myCounter' MVU component.
Let's see how it is coded :
First let's create some helpers using the m function from MVU
const div = m("div") // div maker
let button = m("button") // button maker
let styleCounter = `
display:flex
`
let styleButton = `
color:red
`
let styleValue = `
font-size: 24px;
margin-left: 10px;
margin-right: 10px;
user-select: none;
`
const styleButtons = {style:styleButton}
And now the actual implementation of our 'counter' using dom, udom functions from MVU and our previous helpers
function myCounter(elt) {
let state = elt.state;
let inc = (incr) => () => {state.count += incr; elt.update()};
let counter = dom();
button("inc", styleButtons).onclick = inc(1);
div(`<div>Counter : ${state.count}</div>`, {style:styleValue});
button("dec", styleButtons).onclick = inc(-1);
udom();
counter.style = styleCounter;
return counter;
}
You are certainly wondering where is morphdom in this piece of code ?
In fact render is an alias for morphdom.
It's called whenever we click on the buttons through the update method.
Let us now use our newly web component :
<my-counter init="27"></my-counter>
<my-counter init="13"></my-counter>
<my-counter init="9"></my-counter>
I hope you see how esay it is to create a simple web component using MVU functions, no hooks, no bindings, no need to modify directly the elements...
Of course, it is not complete, but for a first try it does the job.
Here is the full code :
import "https://cdn.jsdelivr.net/gh/artydev/mvu@DMLMorph/dist/mvu.es.js";
const div = m("div")
let button = m("button")
let styleCounter = `
display:flex
`
let styleButton = `
color:red
`
let styleValue = `
font-size: 24px;
margin-left: 10px;
margin-right: 10px;
user-select: none;
`
const styleButtons = {style:styleButton}
function myCounter(elt) {
let state = elt.state;
let inc = (incr) => () => {state.count += incr; elt.update()};
let counter = dom();
button("inc", styleButtons).onclick = inc(1);
div(`<div>Counter (${state.item}) : ${state.count}</div>`, {style:styleValue});
button("dec", styleButtons).onclick = inc(-1);
udom();
counter.style = styleCounter;
return counter;
}
class MyCounter extends HTMLElement {
constructor() {
super()
this.state = {
item: this.getAttribute("item"),
count: Number(this.getAttribute("init")) || 0
}
}
connectedCallback () {
this.append(myCounter(this))
}
update() {
render(this, myCounter(this))
}
}
customElements.define('my-counter', MyCounter);
You can test it here : WebComponentMorphDom
Top comments (0)