gopherjs 是把 go 編譯爲 js 的工具。 vecty 是基於 gopherjs 的一種相似 React 的開發框架。javascript
go get -u github.com/gopherjs/gopherjs go get -u github.com/gopherjs/vecty
vecty 自帶的例子在 example 目錄,有 todomvc 和 markdown 編輯器。java
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/ ,則能夠查看運行結果。node
這個例子中,定義了組件 MyComponent,須要內嵌 vecty.Core 結構,實現 vecty.Component 接口要求的 Render 方法。git
Render 方法負責構建表明組件的 HTML。github
再看 main 方法,調用 vecty.SetTitle 方法設置標題,調用 vecty.RenderBody(&MyComponent{}) 方法把 MyCompoent 組件渲染爲文檔的 body。瀏覽器
回到 MyComponent 的 Render 方法,在 Button 內包含 Markup, Markup 內包括 event.Click,給 Button 附加了 click 事件處理函數 onButtonClick。markdown
事件處理函數 onButtonClick 修改了此組件的 btnCount 字段,而後調用 vecty.Rerender 方法從新渲染此組件,界面上就能看到按鈕上的文字被改變了。mvc
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。dom
在事件處理函數中引用組件渲染出的某個 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
,就能直接對輸入框進行操做,好比獲取輸入框的內容和清空輸入框內容。