gopherjs 是把 go 编译为 js 的工具。 vecty 是基于 gopherjs 的一种类似 React 的开发框架。
安装 gopherjs 和 vecty
go get -u github.com/gopherjs/gopherjs
go get -u github.com/gopherjs/vecty
vecty 自带的例子在 example 目录,有 todomvc 和 markdown 编辑器。
简单的例子
package main
import (
"strconv"
v "github.com/gopherjs/vecty"
"github.com/gopherjs/vecty/elem"
"github.com/gopherjs/vecty/event"
)
func main() {
v.SetTitle("title message swt")
v.RenderBody(&MyComponent{})
}
type MyComponent struct {
v.Core
btnCount int
}
func (mc *MyComponent) onButtonClick(e *v.Event) {
println("click my component button")
mc.btnCount++
v.Rerender(mc)
}
func (mc *MyComponent) Render() v.ComponentOrHTML {
return elem.Body(
elem.Button(
v.Markup(
event.Click(mc.onButtonClick),
),
v.Text("btn"+strconv.Itoa(mc.btnCount)),
),
)
}
运行它
在 $GOPATH/src/ele/gopherjs/t1 文件写下这个文件,命名为 t1.go。然后 cd 到 t1 文件夹,运行命令 gopherjs serve
,将会在 localhost:8080 运行服务,使用浏览器访问 http://localhost:8080/ ,则可以查看运行结果。
解释
这个例子中,定义了组件 MyComponent,需要内嵌 vecty.Core 结构,实现 vecty.Component 接口要求的 Render 方法。
Render 方法负责构建代表组件的 HTML。
再看 main 方法,调用 vecty.SetTitle 方法设置标题,调用 vecty.RenderBody(&MyComponent{}) 方法把 MyCompoent 组件渲染为文档的 body。
回到 MyComponent 的 Render 方法,在 Button 内包含 Markup, Markup 内包括 event.Click,给 Button 附加了 click 事件处理函数 onButtonClick。
事件处理函数 onButtonClick 修改了此组件的 btnCount 字段,然后调用 vecty.Rerender 方法重新渲染此组件,界面上就能看到按钮上的文字被改变了。
定义组件结构
type Comp1 struct {
v.Core
A int `vecty:"prop"`
}
加上 vecty:"prop"
才是一个合格的组件属性。如果不给 A 字段加这个 tag,那么在 Comp1 的上级组件被重新渲染时,就不会考虑 Comp1 的 A 属性值,就认为 Comp1 没有任何改变,不会重新渲染 Comp1,不会改变 Comp1 的 HTML,不会调用 Comp1 的 Rerender 方法。
如果给 A 字段加上这个 tag,那么在 Comp1 的上级被重新渲染时,就会考虑 Comp1 的 A 的值,与之前的 Comp1 的 A 值对比,如果不同,则认为需要重新渲染 Comp1。
引用底层的 javascript 元素
在事件处理函数中引用组件渲染出的某个 javascript 节点
例子
type AddTodoView struct {
v.Core
store vstore.Store
}
func (atv *AddTodoView) Render() v.ComponentOrHTML {
input := elem.Input()
return elem.Div(
elem.Form(
v.Markup(
event.Submit(func(e *v.Event) {
}).PreventDefault(),
),
input,
elem.Button(
v.Markup(
prop.Type("submit"),
event.Click(func(e *v.Event) {
println("btn click")
node := input.Node()
value := strings.TrimSpace(node.Get("value").String())
if value != "" {
atv.store.Dispatch(addTodo(value))
node.Set("value", "")
}
}),
),
v.Text("Add Todo"),
),
),
)
}
以上代码中,为了简单,直接把按钮的 click 事件处理函数定义在组件的 Render 方法中,在事件处理函数内引用了外部变量 input,调用它的 Node 方法获取底层的输入框 javascript 对象,类型为 *js.Object
,就能直接对输入框进行操作,比如获取输入框的内容和清空输入框内容。
来源:oschina
链接:https://my.oschina.net/u/1248114/blog/3044229