Chapter 03

SpaGoの基本

NoboNobo
NoboNobo
2020.11.15に更新

あらかじめ必要なもの

  • go:1.14以降 or tinygo:v0.14.1以降
  • git:2.0.0以降
  • spago:1.0.0以降: コマンドラインツール

コマンドラインツールのインストール

go env -w GO111MODULE=on
go get -u github.com/nobonobo/spago/cmd/spago

SpaGoアプリケーションの構造

  • アプリケーション実装(Goで書きます)
  • HTML、CSS、アセットの準備は従来と同じです
  • SpaGoマークアップ(Goで書きます)
  • JSライブラリ利用(Goで書きます)

下ふたつは支援機能を用意しています(後述)。

BASIC な開発フロー

プロジェクトの作成

mkdir sample1
cd sample1
git mod init sample1

"main.go"ファイルの内容を作成します。
まずは以下の内容にしてください。

package main

import (
	"github.com/nobonobo/spago"
)

func main() {
	spago.RenderBody(&Top{})
	select {}
}

Top コンポーネントの作成

spago new コマンドを使って、Topコンポーネントの雛形を作成します。

spago new -p main Top

フォルダ内は以下のようなファイル一覧になります。

  • sample1/
    • main.go
    • top.go
    • top.html
    • go.mod

このあとtop.htmlに HTML を書いてspago generateコマンドで
Top コンポーネントのレンダラを生成しますが、このspago generateコマンドは
top.gogo generateコマンドとして記入済みです。

HTML の記述

top.html に body タグ以下を記述します。

<body>
  <h5>Hello World!</h5>
</body>

開発サーバーの起動

spago server

最初の表示を確認

以下の URL をブラウザで開きます。

open http://localhost:8080

開発サーバーは wasm ファイルのリクエストを受けると以下の2つの処理を実行します。

  • go generate ./...
  • go build .

結果、top_gen.goが生成され、画面に top.html 相当の表示が出ます。

top_gen.go の内容

package main

import (
	"github.com/nobonobo/spago"
)

// Render ...
func (c *Top) Render() spago.HTML {
	return spago.Tag("body",
		spago.Tag("h5",
			spago.T("Hello World!"),
		),
	)
}

HTML 記述の修正と反映

このまま、top.html の内容を編集し、リロードすれば反映されるのを確認してみましょう。
h5 タグを button タグに書き換えます。

<body>
  <button>Hello World!</button>
</body>

リロードすると top_gen.go の内容は以下のように変更され、ブラウザの表示もボタンになっています。

package main

import (
	"github.com/nobonobo/spago"
)

// Render ...
func (c *Top) Render() spago.HTML {
	return spago.Tag("body",
		spago.Tag("button",
			spago.T("Hello World!"),
		),
	)
}

クリックイベントのハンドリング

次にボタンクリックイベントを実装してみます。
top.go の後半にfunc (c *Top) OnClick(ev js.Value)メソッドを追記します。

package main

import (
	"syscall/js"

	"github.com/nobonobo/spago"
)

//go:generate spago generate -c Top -p main top.html

// Top  ...
type Top struct {
	spago.Core
}

func (c *Top) OnClick(ev js.Value) {
    js.Global().Call("alert", "button clicked!")
}

HTML でのイベントマッピング

top.html を以下のように修正します。

<body>
  <button @click="{{c.OnClick}}">Hello World!</button>
</body>

リロード後、ボタンクリックでアラートが表示されることが確認できるはずです。

top_gen.go の内容をみてみましょう。

package main

import (
	"github.com/nobonobo/spago"
)

// Render ...
func (c *Top) Render() spago.HTML {
	return spago.Tag("body",
		spago.Tag("button",
			spago.Event("click", c.OnClick),
			spago.T("Hello World!"),
		),
	)
}

spago.Event の記述がイベントマッピングの記述です。

プロパティと再描画

次は DOM アップデートを試します。

  • Top 構造体に「Counter int」プロパティを追加。
  • クリックイベントは以下のように変更します。
func (c *Top) OnClick(ev js.Value) {
	c.Count++
	spago.Rerender(c)
}

top.html は以下のように変更します

<body>
  <button @click="{{c.OnClick}}">{{c.Count}}</button>
</body>
  • クリック->Count プロパティインクリメント
  • spago.Rerender(c)により Top コンポーネントが再描画
  • 結果、ボタンの表記の数値が変更されます

DOM 更新には差分抽出してから適用されますので、ボタン表記だけの差分であればボタン表記だけが変更されます。(この場合、ボタンに乗ったフォーカスが失われることはありません。)

以上が基本の開発フローです。