我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第4篇文章,点击查看活动详情
在上一篇文章中,我们讲解了如何通过 JavaScript 调用 Go 编写的函数。
如何通过 JavaScript 运行用 Go 编写的 WebAssembly 模块?
这一篇文章主要介绍如何在 Go 中访问 DOM API。
文章中的代码是使用上篇文章中的代码作为基础进行开发的,如果读不懂可以去看一下上一篇文章。
访问 DOM API
我会带大家做一个小案例,这里案例会使用 go 的 crypto/rand 库生成 0-10 万之间的真随机数,并将它放置到 p 标签中输入到页面上。
首先实现一个 myRand 函数,用来生成随机数。
func myRand() (*big.Int, error) {
n, err := rand.Int(rand.Reader, big.NewInt(100000))
return n, err
}
然后实现包裹函数。
func randWrapper() js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
jsDoc := js.Global().Get("document")
if !jsDoc.Truthy() {
return "document is not defined"
}
containerEl := jsDoc.Call("getElementById", "rand-container")
if !containerEl.Truthy() {
return "rand-container is not find"
}
p := jsDoc.Call("createElement", "p")
n, err := myRand()
if err != nil {
return "unable to generate random number"
}
p.Set("innerText", n.Text(10))
containerEl.Call("append", p)
return nil
})
}
包裹函数中的代码主要就是在 Go 中访问 DOM API 的代码,我在这里给大家解释一下。
- js.Global():该方法的返回值对应的是 JavaScript 的全局对象,也就是浏览器的 window 对象。
- obj.Get("prop"):obj 代表 JavaScript 中的某个对象,Get 方法可以访问它的 key。就像是 JavaScript 中的 obj.prop。
- obj.Truthy():该方法和 obj == true 类似,用来判断是否为 nil。
- obj.Call("method"):该方法用来调用某个对象身上的方法,类似于 JavaScript 中的 obj.method()。我们也可以在后面传递其他参数,作为实际被调用方法的参数。
- obj.Set("prop", value):obj 代表 JavaScript 中的某个对象,Set 方法可以设置它的属性。就像是 JavaScript 中的 obj.prop = value。值得一提的是,如果想获取或者设置全局变量,都可以通过 jsGlobal().Get/jsGlobal().Set 来操作。
解释完,上面的代码就不难理解了。
我们首先获取 document 对象,然后再去获取一个 id 为 rand-container 的元素。
再去创建一个 p 元素,调用 rand 方法获取随机数,把随机数设置为 p 的内容。
最后把 p 添加到 rand-container 元素中。
实现好这两个函数后,在 main 方法中将这个方法加入到全局对象中。
js.Global().Set("addRand", randWrapper())
然后将代码编译为 wasm 模块。
来到 index.html 中,添加两个元素。
<div id="rand-container"></div>
<button onclick="addRand()">add rand</button>
启动服务器。
go run main.go
来到浏览器中看一下效果。
大功告成!