go 前端框架 vecty 學習
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
,就能直接對輸入框進行操作,比如獲取輸入框的內容和清