Vueの新バージョン、3.0のbeta版が出たらしいので、みんな大好きTODOリストを作って書き味を試してみようと思います。
なお、完成したコードはこちらにおいてあります。よければ参考にしてください。 https://github.com/yubachiri/vue3-todo-sample
CLIのインストール
僕のCLIはだいぶ古かったです。過去にVueを利用してしばらく触ってない場合は、念のため最新のものを入れておきましょう
$ npm uninstall vue-cli -g
$ npm install @vue/cli@4.4.1 -g
$ vue version
バージョン指定をしない場合、2020/5/29時点では3.0.1が入りました。が、4.0.1で修正されているバグに遭遇したり、vue-next
が入らなかったため、最新版を指定しています。参照: Create new project - TypeError: api.assertCliVersion is not a function
Vue3を触れる環境構築
プロジェクト作成
$ vue create sample-project
選択肢が出ますが、defaultでOKです。プロジェクトが作成できたら、試しに起動してみましょう。
$ cd sample-project
$ npm run serve
http://localhost:8080/ でこの画面が表示されればOKです。
Vue3 ベータ版の導入
公式プラグインを入れます。CLIのバージョンが低いとエラーが出るので、確認しておきましょう。
$ vue add vue-next
これで準備完了です。実装していきましょう。
実装
HelloWorldする
まずは挨拶から。これを App.vue
に丸々コピペしてください。今回はApp.vue
しか触りません。
<template>
<div id="app">
<p>
{{state.greet}}, {{state.version}}
</p>
</div>
</template>
<script>
import { defineComponent, reactive } from 'vue'
export default defineComponent({
setup() {
const state = reactive({
greet: "Hello",
version: "Vue 3"
})
return {
state
}
}
})
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
今までのVueとは一味違った構文ですね。従来 data()
で書いていたstateは、reactive
で定義できるようになっています。なお、defineComponent
はts採用時に効果を発揮するものだそうです。コンポーネント内での型推論が可能になるとのこと。今回はプロジェクトの作成をデフォルト設定で行ったので、恩恵を受けられません。 参考 composition-api#typescript
表示される画面はこちら。
いいですね。ではTODOしていきましょう。
TODOアプリ作る
まずはタスクの登録。
<template>
<div id="app">
<input type="text" v-model="state.input" />
<button @click="addTodo">
Add TODO
</button>
<p v-for="todo in state.todos" :key="todo">
{{todo}}
</p>
</div>
</template>
<script>
import { defineComponent, reactive } from 'vue'
export default defineComponent({
setup() {
const state = reactive({
input: "",
todos: [],
})
function addTodo() {
state.todos = [...state.todos, state.input]
state.input = ""
}
return {
state,
addTodo,
}
}
})
</script>
templateには以下の変更を行いました。
- textをバインドしたinputを設置
- 入力された値を配列に追加するためのボタンを設置
scriptの方は、
- todoを格納する配列を定義
- todoを追加する関数を定義
関数は従来 methods
で定義していましたね。自由度が上がっているように見えます。やりようによっては以前より見通しの良いコードになりそうです。
関数は定義したらreturnするようにしましょう。
あとは、todoの完了管理ができるようになったら完成です。簡単ですね。
<template>
<div id="app">
<input type="text" v-model="state.input" />
<button @click="addTodo">
Add TODO
</button>
<p v-for="(todo, index) in state.todos" :key="index">
{{todo}}
<button @click="completeTodo(index)">
Complete
</button>
</p>
<p>Completed</p>
<p v-for="(todo, index) in state.completedTodos" :key="index">
{{todo}}
</p>
</div>
</template>
<script>
import { defineComponent, reactive } from 'vue'
export default defineComponent({
setup() {
const state = reactive({
input: "",
todos: [],
completedTodos: [],
})
function addTodo() {
state.todos = [...state.todos, state.input]
state.input = ""
}
function completeTodo(index) {
state.completedTodos = [...state.completedTodos, state.todos[index]]
state.todos.splice(index, 1)
state.todos = [...state.todos]
}
return {
state,
addTodo,
completeTodo
}
}
})
</script>
templateの変更
- 各todoに完了ボタンを設置
- 完了したtodoを表示
scriptの変更
- 完了したtodoを格納する配列を定義
- todoを完了する関数を定義
です。雑ですが十分でしょう。
まとめ
構文がガラッと変わりますが、stateや関数の定義あたりはReactのfunction componentっぽさを感じて割と好みです。型推論が真価だと思うので、これはts入れるべきでしたね。vue create
で手動設定を選び、ちゃっちゃと入れちゃうのが吉。