Vue.js + Golangでタスクリスト作ってみた
Vue.jsとgolangを使って何か作ってみたかったので試しにタスクリストを作ってみました。
Vue.jsの書き方やgolangのAPI実装はmattnさんのブログを大いに参考にさせて頂きました。
見た目はこんな感じです。
WebアプリケーションフレームワークはEcho、ORMにgormを利用しています。 また、Dockerの勉強も兼ねてフロントエンドとバックエンドの環境を立ち上げられるよう設定ファイルも書いてみました。
バージョン確認
$ go version go version go1.10 darwin/amd64 $ node -v v9.8.0 $ npm -v 5.8.0
なお、環境構築の手順は割愛します。
フロントエンドの実装
タスクリストの機能は次の通りです。 - タスクの一覧表示 - タスク作成 - タスクの完了、及び残タスクに戻す
上記の処理はsrc/components/Todo.vueにあります。 下のコードはjsが動く部分です。
<script> import axios from 'axios' export default { name: 'Todo', data () { return { newTask: '', todos: [] } }, created: function () { axios.get('http://localhost:1323/tasks') .then((response) => { console.log(response) this.todos = response.data.items || [] }) .catch((error) => { console.log(error) }) }, methods: { addTask: function (todo) { let params = new URLSearchParams() params.append('text', this.newTask) params.append('done', false) axios.post('http://localhost:1323/tasks', params) .then((response) => { this.todos.unshift(response.data) this.newTask = '' }) .catch((error) => { console.log(error) }) }, updateTask: function (todo) { let params = new URLSearchParams() params.append('done', !todo.done) axios.put('http://localhost:1323/tasks/' + todo.id, params) .then((response) => { todo.done = !todo.done console.log(response) }) .catch((error) => { console.log(error) }) } } } </script>
created()はページをロードした時だけ実行されます。
また、データのやり取りはすべてAjaxでAPIを実行して結果を取得するようにしています。
axios使いやすいです。
バックエンドの実装
バックエンドのAPIはGolang + Echo + Gormで実装しています。
ミドルウェアやルーティングの設定はmain.goでして実処理はhandler.goに書いてます。
model/にはタスクのデータ定義やデータアクセスの処理を定義していて、ビジネスロジックは書かずシンプルにしています。
func (m *Model) FindAll() (tasks []model.Task, err error) { err = m.DB.Table(table).Find(&tasks).Error return } func (m *Model) Create(task model.Task) (t model.Task, err error) { t = task err = m.DB.Table(table).Create(&t).Error return } func (m *Model) Update(task model.Task) (t model.Task, err error) { t = task err = m.DB.Table(table).Where("id = ?", task.ID).Update("done", task.Done).Error return }
実際のデータベース接続処理とも切り離していて、接続処理はdatabase/に定義しています。
func Connect() (*gorm.DB, error) { db, err := gorm.Open("mysql", "root:password@tcp(mysql:3306)/app?charset=utf8&parseTime=True&loc=Local") if err != nil { return nil, err } return db, nil }
また、tasksのテーブル定義はinfra/mysql/sqls/1_init.sqlに記載してます。
環境構築
今回紹介したアプリはなるべくdocker-composeで再現できるようにしていますが、APIのビルドは事前に実行する必要があります。本当はそこもMakefile使う等で自動化したい。。
cd TodoList/backend/service GOOS=linux go build -o api main.go handler.go
基本必要な記述はできるだけ個々のDockerfileではなくdocker-compose.ymlに寄せてます。
version: '2' services: web: container_name: 'web' build: context: ../front/ dockerfile: Dockerfile volumes: - ../front:/app networks: - front ports: - 8080:8080 api: container_name: 'api' build: context: ../backend/service/ dockerfile: Dockerfile networks: - front - datastore ports: - 1323:1323 mysql: container_name: 'db' build: context: ./mysql/ dockerfile: Dockerfile volumes: - ./mysql/mysql_data:/var/lib/mysql # データの永続化 - ./mysql/sqls:/docker-entrypoint-initdb.d # 初期データ投入 environment: - MYSQL_ROOT_PASSWORD=password #rootパスワードの設定 networks: - datastore ports: - 3306:3306 networks: front: datastore:
webのDockerコンテナは起動時にnpm installとnpm runしてます。 apiコンテナは事前にlinux用にビルドされたバイナリを配置して起動しているだけです。 DBのテーブル定義などはコンテナ構築時に初期データを読み込むようにしています。
- ./mysql/sqls:/docker-entrypoint-initdb.d # 初期データ投入
感想
なんだかんだで今回一番時間かかったのはdockerを使った環境構築。。。
Vue.jsを使ってみたくてアプリを作ってみましたが、ファイル分割しやすいしstyleとhtmlとjsをコンポーネント毎に分けられるので処理を理解しやすい。axiosなどの使いやすいライブラリもあるので開発するならVue.jsでいい感じ。レイアウトのデザインを作るためのライブラリも充実していてElementやVuetifyがあります。Vuetifyは簡単にマテリアルデザインが作れる感じなので使ってみたい。