1. 程式人生 > >go 前端框架 vecty 學習

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