This package allows to build frontend applications in Go targeting Webassembly. It provides a conveniant syntax close to the hyperscript one in the JavaScript lands and aims to provide efficient way to deal with the DOM. If you're not familiar the Virtual DOM notion, I suggest you take a look at this document.
This module has been inspired by the awesome work of @mbasso on https://github.com/mbasso/asm-dom.
Want to see go-vdom-wasm in action?
You have to make some little configuration that are well explained in the Go + WASM wiki - Getting started guide.
If you prefer a quickest solution, you can also rely on the go-wasm-cli utility. It allows to create a WASM application in one command line and to have hot reload while coding.
In your favorite terminal
$ GOOS=js GOARCH=wasm go get github.com/mfrachet/go-vdom-wasm
Let's define the root of our go-vdom-wasm
application. Everything that the library will work on is inside that div
:
<!-- index.html-->
<div id="app"></div>
Let's now Patch
that node with a virtual one to make something happen:
// main.go
rootNode := vn.H("div", "Hello world")
vn.Patch("#app", rootNode)
In this example, we set a class="navbar"
to the underlying ul
element
vn.H("ul", &vn.Props{"class": "navbar"}, vn.Children{
vn.H("li", "First item"),
vn.H("li", "Second item"),
}),
The DOM representation of the previous snippet is:
<ul class="navbar">
<li>First item</li>
<li>Second item</li>
</ul>
The Ev
structure allows to pass functions to handle specific events.
In this example, we set a click event on of the the li
:
func handleClick(args []js.Value){
fmt.Println("I've been clicked!")
}
func main() {
rootNode := vn.H("ul", &vn.Props{"class": "navbar"}, vn.Children{
vn.H("li", &vn.Ev{"click": handleClick}, "First item"),
vn.H("li", "Second item"),
})
vn.patch("#app", rootNode)
}
This module binds the event using the addEventListener
API
select{}
at the end of the main
function
For efficient diffing while you're relying a list of items, you can rely on a key
parameter:
vn.H("div", vn.Children{
vn.H("span", attrsChecked, "Some text"),
}, &vn.Key{"UNIQUE KEY"})
The key aims to identifiy a Node. It has to be unique and will ensure a quick comparison before handling the computation. The idea is the same (less advanced actually, but here's the idea) as the React key system.
- Add more tests 🤦♀️ 🤦♂️
- Find a better solution to compare two virtual nodes
- Ensure consistency and avoid unecessary rerendering that sometimes occur for the same DOMNodes ❓
- Make a better abstraction concerning the reconciler (it's a really first step)
- Rely on Go good practices (reference passing, better algorithms and so forth...)
- Generating the API doc and adding decent comment in code
- Find a way to abstract the
[]js.Value
passed in every event handler