2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vuetifyで30分でTodoアプリを作るチュートリアル

Last updated at Posted at 2021-12-09

初めに

はじめましてKouと申します。
仕事でVuetifyを使う機会があったので備忘録と共有を含めて簡単なTodoアプリを作る方法を紹介します!

これでVuetifyの便利さが伝わったらいいなという思いを込めていきます!

完成リポジトリ:https://github.com/KouWakai/VuetifyTodo

完成イメージ

これが大体30分くらいで作れます

822e1060d6778fa606f510a0cb801a75.png

このチュートリアルで必要なもの

Vue-cliとVuetifyのcliパッケージのみです。
次の環境構築でインストール方法は解説します。
nodejsはOSによって違うのと先人がわかりやすいやり方を解説してくださっているのでそちらでお願いいたします

以下リンクです。

nodejs
vue
vuetify

環境構築

自分で公式ドキュメント読んで、できる方は飛ばしちゃってOKです!

vue cliのインストール

以下のコマンドでインストールしてください

$ npm install -g @vue/cli

vueプロジェクト作成※必ずvue2を選択

せっかくなのでちょっといじりましょう。
manually select featuresを選択してください。

Vue CLI v4.5.15
? Please pick a preset: 
  todoapp ([Vue 2] dart-sass, babel, router, vuex) 
  Default ([Vue 2] babel, eslint) 
  Default (Vue 3) ([Vue 3] babel, eslint) 
❯ Manually select features 

Linter/Formatterはうるさいので消しておきましょう。
カーソルを矢印キーで動かしてスペースを押すと丸を消せます。

? Check the features needed for your project: 
 ◉ Choose Vue version
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
❯◯ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing

ここは必ず2.xでお願いします!!
というのもVuetifyはvue3に対応していないためです。
vue3にしてnpm run serveするとコンパイルが通りません。ちょびハマりポイントなので注意

? Choose a version of Vue.js that you want to start the project with (Use arro
w keys)
❯ 2.x 
  3.x 

package.jsonでいきましょう。

? Where do you prefer placing config for Babel, ESLint, etc.? 
  In dedicated config files 
❯ In package.json 

nでいいです。一応、yにすると今回の選択をプリセットとして保存できます。

? Save this as a preset for future projects? (y/N) n

Vuetify導入

cd todoappでvueプロジェクトのディレクトに入ります。

cd todoapp

そして以下のコマンドでVuetifyを導入します

vue add vuetify

Defaultでいきましょう。ということでEnterを押してください

? Choose a preset: (Use arrow keys)
  Configure (advanced) 
❯ Default (recommended) 
  Vite Preview (Vuetify 3 + Vite) 
  Prototype (rapid development) 
  Vuetify 3 Preview (Vuetify 3) 

こんな感じになったら終了です。環境構築お疲れ様でした!

✔  Successfully invoked generator for plugin: vue-cli-plugin-vuetify
 vuetify  Discord community: https://community.vuetifyjs.com
 vuetify  Github: https://github.com/vuetifyjs/vuetify
 vuetify  Support Vuetify: https://github.com/sponsors/johnleider

さあコーディングするぞ!

1.ワイヤーフレームを持ってくる

todoappをエディターで開いてください。この記事ではVSCODEを使います。

開いたらターミナルで以下のコマンドを打ってください

npm run serve

コンパイルが終わったら、http://localhost:8080/ を開きましょう。(8080があいてなかったら8081になったりします。)

210757a7dcb5bc46304a9c28a8fc71a0.png

この画面になったらうまく環境構築がいってます。これがVuetifyをデフォルトのvueに導入した直後の状態です。

ここからロジックを追加してtodoappにしていきます。

todoapp/src/App.vue

を開いてください。v-appやらなんやら書いてますね。ここをいじっていきます。

ワイヤーフレームを使いましょう。以下のリンクでVuetify公式のワイヤーフレームのページにいってください。

Side navigationを使いましょう。以下のリンクかワイヤーフレームのページのside navigationをクリック

下のようなページが出てくるので右隅にあるアイコンをクリック!

33162b6d0b4b66da54ae1f3a21ddeb4a.png

そしたらgithubのリポジトリにさっきのページのソースが出てくるので全部コピー
5ce91aea6184fae2862068cbcf331e84.png

さっき開いた todoapp/src/App.vueに貼り付けてください。
もともとはいってたソースは消してください。

そしてlocalhost:8080d(以下、開発サーバー)を開くとワイヤーフレームが表示されているはずです。

Todoapp/src/components/Todo.vueを作成

19行目あたりのv-main内のスコープにを記入

    <v-main>
      <Todo />
    </v-main>

25行目から以下のコードでTodo.vueをimport、exportしてください。

<script>
import Todo from './components/Todo.vue'
  export default {
      components:{
          Todo,
      },
  }
</script>

Todo.vueを開いてtemplateとh1タグを書いて好きな文字を入力してください

<template>
    <h1>Hello World!!</h1>
</template>

開発サーバーを見ると下のようになっているはずです!

fea10fd5b37723ae2fbc252c1626c437.png

このTodo.vueにコーディングしていきましょう!

2.コンポーネントを駆使する

サイドバーのListsをクリック
8e1d3d41603cbe85e70d9af61931c0af.png

するとページの真ん中辺りにいい感じのAction stackがありますね。<>をクリックしてください

081396fb2513eba3c1bc35b31b3b3ff7.png

するとソースがでてくるのでをすべてコピー

<template>
  <v-card
    class="mx-auto"
    max-width="500"
  >
    <v-toolbar
      color="pink"
      dark
    >
      <v-app-bar-nav-icon></v-app-bar-nav-icon>

      <v-toolbar-title>Inbox</v-toolbar-title>

      <v-spacer></v-spacer>

      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>

      <v-btn icon>
        <v-icon>mdi-checkbox-marked-circle</v-icon>
      </v-btn>
    </v-toolbar>

    <v-list two-line>
      <v-list-item-group
        v-model="selected"
        active-class="pink--text"
        multiple
      >
        <template v-for="(item, index) in items">
          <v-list-item :key="item.title">
            <template v-slot:default="{ active }">
              <v-list-item-content>
                <v-list-item-title v-text="item.title"></v-list-item-title>

                <v-list-item-subtitle
                  class="text--primary"
                  v-text="item.headline"
                ></v-list-item-subtitle>

                <v-list-item-subtitle v-text="item.subtitle"></v-list-item-subtitle>
              </v-list-item-content>

              <v-list-item-action>
                <v-list-item-action-text v-text="item.action"></v-list-item-action-text>

                <v-icon
                  v-if="!active"
                  color="grey lighten-1"
                >
                  mdi-star-outline
                </v-icon>

                <v-icon
                  v-else
                  color="yellow darken-3"
                >
                  mdi-star
                </v-icon>
              </v-list-item-action>
            </template>
          </v-list-item>

          <v-divider
            v-if="index < items.length - 1"
            :key="index"
          ></v-divider>
        </template>
      </v-list-item-group>
    </v-list>
  </v-card>
</template>

todo.vueに上書きします。
そして、scriptをクリックしてをすべてコピー。
c4a3453bdd9ff1307deb88a00bd455d7.png

<script>
  export default {
    data: () => ({
      selected: [2],
      items: [
        {
          action: '15 min',
          headline: 'Brunch this weekend?',
          subtitle: `I'll be in your neighborhood doing errands this weekend. Do you want to hang out?`,
          title: 'Ali Connors',
        },
        {
          action: '2 hr',
          headline: 'Summer BBQ',
          subtitle: `Wish I could come, but I'm out of town this weekend.`,
          title: 'me, Scrott, Jennifer',
        },
        {
          action: '6 hr',
          headline: 'Oui oui',
          subtitle: 'Do you have Paris recommendations? Have you ever been?',
          title: 'Sandra Adams',
        },
        {
          action: '12 hr',
          headline: 'Birthday gift',
          subtitle: 'Have any ideas about what we should get Heidi for her birthday?',
          title: 'Trevor Hansen',
        },
        {
          action: '18hr',
          headline: 'Recipe to try',
          subtitle: 'We should eat this: Grate, Squash, Corn, and tomatillo Tacos.',
          title: 'Britta Holt',
        },
      ],
    }),
  }
</script>

Todo.vueの74行目以降に貼り付けます。

すると開発サーバーが以下のようになります。

836d1ba808bdc9f03e9e31f98c2b0ada.png

3.本当のコーディング

12行目のInboxをTodoに変えましょう

      <v-toolbar-title>Todo</v-toolbar-title>

80行目から109行目までのitemsオブジェクトの要素を消します。
そして以下のようにTodoリストのタスクのようなものを追加します。

      items: [
            {
                id:1,
                task:'Vuetifyを勉強する',
                done: true,
            },
            {
                id:2,
                task:'JSを勉強する',
                done: false,
            },
      ],

この状態で保存してもまだ画面には出てきません。ロジックを書きましょう。

まずv-list-item-group内の要素31行目から63行目を削除しましょう。そしてv-list-item-groupのプロップスも消します。

v-listのtwo-lineを消します。すると以下の状態になっているはずです。

    <v-list>
      <v-list-item-group
      >
      </v-list-item-group>
    </v-list>

v-list v-forを追記しましょう。カラムを12に設定します。Vuetifyは特定のコンポーネントはcolsというapiをもっていてこれでカラムを指定できます。

    <v-list v-for="item in items" :key="item.id" cols="12">

v-list-item-group内にv-list-itemを書きましょう
v-list-item-content
v-list-item-title
それからitem.idをマスタッシュ構文で記載。

次にtodoのタスクを表示したいので、さきほどのようにv-list-item-contentから作り、マスタッシュ構文でitem.taskを記載します。

    <v-list v-for="item in items" :key="item.id" cols="12">
      <v-list-item-group
      >
        <v-list-item>
                    <v-list-item-content>
                        <v-list-item-title>{{item.id}}</v-list-item-title>
                    </v-list-item-content>
                    <v-list-item-content>
                        <v-list-item-title>{{item.task}}</v-list-item-title>
                    </v-list-item-content>
        </v-list-item>
      </v-list-item-group>
    </v-list>

そうするとようやくタスクが表示できます!33fc7b7e28c8bf5913a79c60b0955c87.png

todoリストといえばチェックボックスですね!ということでチェックボックスとそのロジックをつくりましょう。

4.チェックボックスとクリックイベント

非常に簡単です。v-list-itemにv-list-item-aciton
v-checkboxを追加するだけです。


        <v-list-item>
            <v-list-item-action>
                <v-checkbox></v-checkbox>
              </v-list-item-action>

                    <v-list-item-content>
                        <v-list-item-title>{{item.id}}</v-list-item-title>
                    </v-list-item-content>
                    <v-list-item-content>
                        <v-list-item-title>{{item.task}}</v-list-item-title>
                    </v-list-item-content>
        </v-list-item>

e646e8fe5d6a37bb6e8dcdbc72a1d0d4.png

ただこれだけだと先程itemsオブジェクトに設定したdoneの値が反映されないのでコードを追加しましょう

v-checkboxにinput-valueを追加。

<v-checkbox  :input-value=item.done></v-checkbox>

これでitemsのdoneの値を読み込めるようになりました。今度はこれをクリックシた際にitemsに反映させるようにしましょう。

v-checkboxに@click="done(item.id)"を追加します

<v-checkbox  :input-value=item.done @click="done(item.id)"><v-checkbox>

scriptタグのdataの後に以下のメソッドを追加します。
dataのselected: [2],は消しちゃいましょう。

    methods:{
        done(id){
            this.items[id].done = !this.items[id].done
            console.log(this.items[id].done)
        }
    }

このメソッドはチェックボックスがクリックされると現在bool型の状態とは逆の状態を設定します。
試しに保存してクリックしてみましょう。

338d3377fb06e304524c671fbd775f92.png

何回か同じタスクのチェックボックスをクリックして開発者ツールのコンソールにtrue、falseがでればOKです!

次は不要なタスクを削除できるようにしましょう。

40行目以降に以下を追加してください。
削除するイベントを起こしたいのでv-list-item-actionを使い、その中にv-btnを書きます。今回はボタンにアイコンを使うのでプロップにiconを設定します。

<v-list-item-action>
 <v-btn @click="deleteTask(item.id)" icon>               
  <v-icon>
   mdi-backspace
  </v-icon></v-btn>
</v-list-item-action>

以下のようにアイコンが追加されます。これをクリックすると
@clickが走り、deleteTaskメソッドが呼び出されます。メソッドを書きましょう。

be77cafd88f0b672786f22afbc721e6e.png

単純にfilterでクリックされたタスク以外のidを持つものを返します。

        deleteTask(id) {
        this.items = this.items.filter((item) => item.id !== id)
      },

では開発サーバーの方でボタンをクリックしてください。これで消えるはずです。

1点付け加えるとバブリングをさせたくないので@clickにstopをつけて@click.stopを使ったほうがベターです。

詳しくはこの方の記事を参照
https://qiita.com/shizen-shin/items/e25abd34219e1e569496

タスクを追加する

最後にタスクを追加します。先程の削除と似ている処理なので簡単です。

以下をv-listの外に追加します

    </v-list>

          <v-col
          cols="12"
          class="d-flex">
          <v-list-item-content>
            <v-text-field
            v-model="todo"
            label="AddTodo"
            required
          ></v-text-field>
              </v-list-item-content>

              <v-list-item-action>
              <v-btn @click.stop="addTask(todo)" icon>               
                  <v-icon>
                    mdi-plus-circle
                  </v-icon>
                </v-btn>
              </v-list-item-action>
           </v-col>

すると以下のようになります。

fd33847c19636c5edbc519609727a7d4.png

リスト外にカラムを追加しその中のv-text-fieldに追加したいtodoを入力、プラスボタンをクリックしてtodoを追加という流れです。

メソッドを実装しましょう。
deleteTask(id)の下にaddTaskを追加。
itemsにpushして追加するというメソッドです。
ひとまず動くかidは3に固定して動かしてみましょう。

addTask(todo){
        this.items .push({id:3,task:todo,done:false})
      },

このように追加でき、消すこともできますね!

4cc2179625d6164d2f11a2320fda3009.png

idをランダムなものにしてみましょう。
Date関数を使います。

     addTask(todo){
        let id = Date.now().toString()
        this.items .push({id:id,task:todo,done:false})
      },

とりあえず一意な値は振れましたね!

822e1060d6778fa606f510a0cb801a75.png

お疲れ様でした。これにてこのチュートリアルは終了です。

このチュートリアルを通して

まだまだ私も初心者ですが、プロジェクトで実際に使って感動したので、ひとまずVuetifyを使うと公式のコンポーネントを使って効率的に開発できるのを体感していただけたらと思い、共有したくてこのチュートリアルを作成しました。

今回使ったコンポーネントはまだまだVuetifyの一部でほかにも使い勝手のよいコンポーネントがたくさんあるのでこのチュートリアルをきっかけにぜひプロジェクトや個人制作などで使っていただけたらなと思います!

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?