こんにちは!りゅうです。
今回はVuejsの学習をDocker環境で行ったので、DockerとVuejsの環境構築からTODOリストを作るまでの流れを書いてみました。
この記事で実現したいこと
Docker+Vuejsの環境構築とTODOアプリを作れるようにする
参考にしたサイト
Vue.jsで作るtodoアプリ
docker-composeでシンプルにvue.js環境構築
Vueのアプリを動かすコンテナを作成していきます。
フォルダ構成は以下の通りです。serverフォルダはwebコンテナのappフォルダのマウント先です。
PS C:\Users\User\Desktop\DockerVuejs> tree /f フォルダー パスの一覧 ボリューム シリアル番号は 105F-A1E1 です C:. │ docker-compose.yml │ ├─docker │ └─web │ Dockerfile │ └─server
docker-compose.yml
version: '3.8'
services:
web:
container_name: web
build: ./docker/web
ports:
- 8080:8080
volumes:
- ./server:/app:cached
tty: true
stdin_open: true
privileged: true
command: /bin/sh
Dockerfile
FROM node:14.15.0-alpine WORKDIR /app RUN apk update && \ npm install && \ npm install -g npm && \ npm install -g vue-cli
docker-compose.ymlとDockerfieを作成したら、以下のコマンドでコンテナイメージの作成とコンテナの起動を実行
# イメージのビルドとコンテナ起動を同時に行う --buildは強制ビルドするオプション docker-compose up -d --build # 別々に行う場合 # イメージのビルド docker-compose build # コンテナの起動 -dはバックグラウンドで行うオプション docker-compose up -d
ビルドと起動ができたら、コンテナに入りvueのデフォルトAppを作成
# コンテナに入る docker-compose exec web /bin/sh # VueのデフォルトApp作成 /app # vue init webpack
デフォルトApp作成時、色々聞かれますが、特になければ回答はYesと基本的なパッケージを選択で問題ないです。
ホスト側のserverフォルダに色々追加されるので、その中から config>index.js を探して、修正していきます。

# hostをlocalhot→0.0.0.0 host: '0.0.0.0', // can be overwritten by process.env.HOST
# pollをfalse→true poll: true, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
pollをfalse→trueでファイルの変更を起動中に検知
デフォルトAppの作成が終わったら、以下のコマンドでAppを起動
# デフォルトAppの起動(コンテナに入った状態で実行) /app # npm run dev
localhost:8080にアクセスしてデフォルトの画面が表示されればOKです。

ポート8080が使用されている場合は使用しているものを閉じるか、 config>index.js のport:8080 を空いているポートに変更し、docker-compose.ymlもそれに合わせて修正してあげれば、再設定したポートで表示できるようになります。
docker-compose.ymlを修正した場合は再ビルドをお忘れなく、自分はよくやらかしてます(笑)
ポート7080で設定し直す場合
// 8080→7080 port: 7080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
ports:
- 7080:7080
# イメージのビルドとコンテナ起動を同時に行う docker-compose up -d --build
TODOアプリに必要なものを作成、修正していきます。
作成
server\src\components\List.vue
修正
server>src>App.vue
server>src>router>index.js
2つの修正ファイルから修正していきます。
<template>
<div id="app">
<router-view/>
</div>
</template>
export default new Router({
routes: [
// /→/helloに変更
{
path: '/hello',
name: 'HelloWorld',
component: HelloWorld
},
// 元々のHelloWorldの3行をそのままコピペしてHelloWorldを→Listに変更
{
path: '/',
name: 'List',
component: List
}
]
})
server\src\router\index.js ルーターと呼ばれどの画面に遷移するかの制御をします。
Listはこれから作成するTODOリストのファイル名(List.vue)です。
ここまでで、不要なロゴ画像の削除と、ルーターにTODOリスト画面のパスと呼び出すコンポーネントを登録しました。
TODOリストの画面部分を作成していきます。
入力部分とボタン押下時リストを追加するメソッド(ロジックは後述)をまず記述
<template>
<div id="app">
<h2>TODO List</h2>
<form v-on:submit.prevent>
<input type="text" v-model="newItem">
<button v-on:click="addItem">Add</button>
</form>
<pre>{{$data}}</pre>
</div>
</template>
<script>
export default {
data () {
return {
newItem: ''
}
},
methods: {
addItem: function (event) {
alert()
}
}
}
</script>
9行目の<pre>{{$data}}</pre> で newItem の中身を確認
addItem メソッドにalert()を書いて追加ボタン押下時のメソッド呼び出し確認

↓

addItemメソッドにロジックの追加、data()に入力内容を複数格納する配列(todos)の追加
<template>
<div id="app">
<h2>TODO List</h2>
<form v-on:submit.prevent>
<input type="text" v-model="newItem">
<button v-on:click="addItem">Add</button>
</form>
<pre>{{$data}}</pre>
</div>
</template>
<script>
export default {
data () {
return {
newItem: '',
todos: []
}
},
methods: {
addItem: function (event) {
if (this.newItem === '') {
return
}
var todo = {
item: this.newItem
}
this.todos.push(todo)
this.newItem = ''
}
}
}
</script>
複数追加できるか確認

↓

一覧表示のテーブル、リストのチェックと削除ボタンを追加
一覧を中央表示、文字を左寄せ、チェック後の取り消し線を<style>タグで調整
確認できたら<pre>{{$data}}</pre>は削除
<template>
<div id="app">
<h2>TODO List</h2>
<form v-on:submit.prevent>
<input type="text" v-model="newItem">
<button v-on:click="addItem">Add</button>
</form>
<table>
<tr v-for="(todo, key) in todos" :key="key">
<td><input type="checkbox" v-model="todo.isDone"></td>
<td><span v-bind:class="{done: todo.isDone}">{{todo.item}}</span></td>
<td><button v-on:click="deleteItem(key)">Delete</button></td>
</tr>
</table>
</div>
</template>
<script>
export default {
data () {
return {
newItem: '',
todos: []
}
},
methods: {
addItem: function (event) {
if (this.newItem === '') {
return
}
var todo = {
item: this.newItem
isDone: false
}
this.todos.push(todo)
this.newItem = ''
},
deleteItem: function (key) {
this.todos.splice(key, 1)
}
}
}
</script>
<style>
#app table{
margin-left: auto;
margin-right: auto;
text-align: left;
}
#app span.done{
text-decoration:line-through;
}
</style>
リストを3つ追加、取り消し線と削除の確認

↓

以上で、完成です。
Vuejsは初歩的な内容だったので、これを機により実用的な部分も学習できたらと思います。
それからDocker、イメージ作成時やコンテナ起動時に多少エラーで悩まされたりしますが、ローカルに一切パッケージをダウンロードせず学習が進められる点は、改めて便利だなと実感しました。
今回は以上になります。
ご覧いただき、ありがとうございました。