TODOアプリ作成
謎todoアプリ作成 第1弾
Vue3 todoアプリ作成① ~ compositionAPI ~ 今ここ
Vue3 todoアプリ作成② ~ Vuex vue-routerを触ってみる ~
Vue3 todoアプリ作成③ ~ tailwindcss 使ってみた ~
Vue3が3ヶ月前(?)にリリースされましたね
Vue2とVue3の変更点の記事を眺めているだけでコードを全く書いていなかったので
今回Todoアプリを作成してみました
作っていくうちに
vue-routerやVuexも試したくなったため 謎todoアプリができあがりました。
正解というものがわからないまま実装していますので、
ここはこうだろ!!など意見ありましたらコメントしていただけますと幸いです。
完成状態
※この記事のみではこの状態まで説明いたしません。
完成コード
https://vue3-todoapp.netlify.app/
環境
vite: 1.0.0-rc.1
vue: 3.0.0-rc.2
vue-router: 4
vuex: 4.0.0-rc.2
Viteでアプリ作成
Viteとはバンドル処理がなく高速に動作するビルドツールでございます。
とにかく早い。。!
以下記事を拝見するとViteについて知ることができますので気になる方は
ご確認よろしくお願いいたします。
【Vite】 Vue3.0もReactも!ノーバンドルなビルドツール「Vite」を試してみる
プロジェクト作成
//以下コマンド実行 ※プロジェクト名をtodo-appとします。
$ npm init vite-app todo-app
作成完了。
アプリ立ち上げ
//作成したプロジェクトへ移動(todo-app)
$ cd todo-app
//パッケージインストール
$ npm i もしくは yarn
$ npm run dev もしくは yarn dev
こんな画面がでます
todo-app
├ node_modules
├ public
│ └ favicon.ico
├ src
│ ├ assets
│ ├ components
│ ├ App.vue
│ ├ index.css
│ └ main.js
├ index.html
├ package-lockjson
└ package.json
コンポーネント作成
componentsディレクトリにて以下ファイル生成
<template>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'TodoList',
});
</script>
<template>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'TodoInput',
});
</script>
注意点
- script lang="ts"とすることで Typescriptで記述することができます。
- コンポーネント作成にてdefineComponentを使用することで型推論することが可能になります。
詳しくはこちらを確認お願いいたします。
コンポーネント表示
仮データを用意し、表示させてみます!
- App.vueファイルにて TodoListファイルをimport
- TodoList.vueにて仮データを用意する。
- TodoInput.vueにてinputとbutton作成。
※TodoInputわざわざ作る必要なくね?となると思われますが、今回emitなど使用してみたかったので作成しました。
お許しを。。
reactiveって何ぞや
data()
の中でstate
を定義していたと思われますが、
composition api
では reactive
を使って定義を行います。
と簡単に書いておきます。
以下記事にてわかりやすく説明されています。
先取りVue 3.x !! Composition API を試してみる
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<TodoList />
</template>
<script>
import TodoList from './components/TodoList.vue'
export default {
name: 'App',
components: {
TodoList
}
}
</script>
<template>
<div>
<ul class="todolist">
<li v-for="todo in state.todoList" :key="todo.todo">{{ todo.todo }}</li>
</ul>
<Todo-input />
</div>
</template>
<script lang="ts">
import { defineComponent, reactive} from 'vue'
import TodoInput from '../components/TodoInput.vue'
export default defineComponent({
name: 'TodoList',
components: {
TodoInput
},
setup() {
// lang="ts"とした場合。 reactiveの中で型定義を行います。
// 仮データを二つ用意したため、二つtodo定義しています。本来は不必要です。
const state = reactive<{ todoList: [{todo: String}, {todo: String}];}>({
todoList: [
{
todo: 'todo1',
},
{
todo: 'todo2',
}
]
});
return { state };
}
});
</script>
<template>
<input type="text">
<button >登録</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
name: 'TodoInput',
});
</script>
注意点
- templeteの中で
state
などのデータもしくは関数
などを記述する際は、return { state, 関数 }
と記述する必要がある。
結果画面
こんな感じでok
実際にTODO追加
次はtodoを入力し、表示させていきます〜〜
1.カスタムイベント作成
2.emitを使用し、イベント発火させる。
<template>
<div>
<ul class="todolist">
<li v-for="todo in state.todoList" :key="todo.todo">{{ todo.todo }}</li>
</ul>
<Todo-input @add-todo="addTodoAction" />
</div>
</template>
<script lang="ts">
import { defineComponent, reactive} from 'vue'
import TodoInput from '../components/TodoInput.vue'
export default defineComponent({
name: 'TodoList',
components: {
TodoInput
},
setup() {
const state = reactive<{todoList: Array<{todo: string>;}>({
todoList: []
});
const addTodoAction = (value: string) => {
state.todoList.push({todo: value})
};
return { state, addTodoAction };
}
});
</script>
<template>
<div>
<input v-model="todoRef" type="text">
<button @click="add">登録</button>
</div>
</template>
<script lang="ts">
import { defineComponent, SetupContext, ref } from 'vue'
export default defineComponent({
name: 'TodoInput',
setup(props, context: SetupContext) {
const todoRef = ref<string>('')
const add = (e) =>{
context.emit('add-todo', todoRef.value);
todoRef.value = ''
};
return { add, todoRef};
}
});
</script>
注意点
-
this.$emit
がcontext.emit
で使用できる。
setup(props, props, context: SetupContext)
と記述されているが、setupの関数内の引数は
第1引数: props
第2引数: context
と決まっているので
setup(context)と書くことはできない。
結果画面
おわり
ちょっと長くなった感がございますのでここで一旦止めます。
次の記事で完了ボタン、詳細ボタンなどを作成していきたいと思います。
正解というものがわからないまま実装していますので、
ここはこうだろ!!など意見ありましたらコメントしていただけますと幸いです。