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
で手動設定を選び、ちゃっちゃと入れちゃうのが吉。