Vue CLIをインストールしプロジェクトを作成する。
$ npm install -g @vue/cli
$ vue --version
@vue/cli 4.5.13
$ vue create todo
$ tree -I node_modules todo
.
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js
エントリーポイント main.js
を見るとVue 3からのGlobal API、createApp()が使われている。
$ cat src/main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
まずは入力フォームを作っていく。
.vue
はSingle File Componentsのファイル。
v-onまたは@
でイベントをハンドリングする。
v-modelはmodelValue
propをinput.valueにバインドし、
入力時にemitされる update:modelValue
eventで更新することで双方向にバインディングする。
Vue 2ではvalue
propを input
eventによって更新していた。
$ cat src/components/Form.vue
<template>
<div>
<input v-model="title" placeholder="TODO">
<button @click="add">add</button>
</div>
</template>
<script>
export default {
name: 'Form',
data() {
return {
title: '',
}
},
methods: {
add() {
this.$emit('add', this.title)
this.title = ''
}
}
}
</script>
<style scoped>
div {
background-color: #ddeedd;
}
</style>
次にTODOを表示するリストを作る。
propsとしてtodoを受け取り、
v-forでループさせ、v-ifでレンダリングする条件を渡す。
v-if
は v-for
より先に評価されるので、同じ要素に含められない。
v-bind または :
を用いることで文字列以外の定数や変数を渡すことができる。
$ cat src/components/List.vue
<template>
<div>
<ol>
<template v-for="(todo, index) in todos" :key="todo.id">
<li v-if="!todo.done">
{{ todo.title }}
<button @click="done(index)">done</button>
</li>
</template>
</ol>
</div>
</template>
<script>
export default {
name: 'List',
props: {
allTodos: Array
},
data() {
return {
todos: this.allTodos,
}
},
methods: {
done(index) {
this.todos[index].done = true
}
}
}
</script>
<style scoped>
div {
background-color: #eeddee;
}
</style>
最後にこれらのコンポーネントを配置する。Formで発火したイベントを受け取りデータを更新するとListも更新される。
$ cat src/App.vue
<template>
<Form @add="addTodo" />
<List :allTodos="allTodos" />
</template>
<script>
import Form from './components/Form.vue'
import List from './components/List.vue'
export default {
name: 'App',
components: {
Form,
List
},
data: () => {
return {
allTodos: []
}
},
methods: {
addTodo(title) {
this.allTodos.push({id: this.allTodos.length + 1, title: title, done: false})
}
}
}
</script>