Blogブログ

TORAT | 2022.10.5

Nuxt.jsでTodoアプリを作ってみた

  • JavaScript

Nuxt.jsとは

Nuxt.jsとは、Vue.jsベースのJavaScriptのフレームワークです。
UIなどフロントエンド向けのフレームワークであるVue.jsをベースにしてWebアプリケーション開発に必要な機能が最初から組み込まれています。

Todoアプリの作成

以下のような簡単なtodoアプリを作ります。

値を入力しsaveで保存、findで検索、allで全件表示機能を持ちます。

Nuxt.jsのインストールとプロジェクトの作成

node.jsのインストール

まずnode.jsをインストールします。

node -v
v16.14.0

Nuxt.jsのインストール

Nuxt.jsにはプロジェクト作成ツールとして create-nuxt-app が用意されています。
今回はこれを使ってnuxt-todo-appという名前のプロジェクトを作成します。

npx create-nuxt-app nuxt-todo-app
npx create-nuxt-app プロジェクト名

インストールが開始されるといくつか質問をされるのでそれぞれ該当するものを選択していきます

create-nuxt-app v4.0.0
✨  Generating Nuxt.js project in nuxt-todo-app
? Project name: (nuxt-todo-app)

プロジェクト名を聞かれます。
何もしなければ先程指定した名前が入るので[Enter]を押します。

? Programming language: (Use arrow keys)
❯ JavaScript
  TypeScript

使用する言語をJavaScriptとTypeScriptから選べます。今回はJavaScriptを選択します。

? Package manager:
  Yarn
❯ Npm

パッケージマネージャーは npm か yarn のどちらを使うかを聞かれます。今回は、npmを選択しました。

? UI framework: (Use arrow keys)
❯ None
  Ant Design Vue
  BalmUI
  Bootstrap Vue
  Buefy
  Chakra UI
  Element
  Oruga
  Primevue
  Tachyons
  Tailwind CSS
  Windi CSS
  Vant
  View UI
  Vuetify.js

UI フレームワークは何を使うかを聞かれます。None選択しましたが、こちらはあとから変更可能です。

? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ Axios - Promise based HTTP client
 ◯ Progressive Web App (PWA)
 ◯ Content - Git-based headless CMS

Nuxt.jsのモジュールはどれを使用するか聞かれます。([スペースキー]で選択、[a]で全選択、[i]で選択解除)

? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ ESLint
 ◯ Prettier
 ◯ Lint staged files
 ◯ StyleLint
 ◯ Commitlint

ESLint、Prettier、Lint staged files、StyleLint を利用するかどうか聞かれます。([スペースキー]で選択、[a]で全選択、[i]で選択解除)

? Testing framework: (Use arrow keys)
❯ None
  Jest
  AVA
  WebdriverIO
  Nightwatch

テストフレームワークは何を使うかを聞かれます。

? Rendering mode: (Use arrow keys)
  Universal (SSR / SSG)
❯ Single Page App

ユニバーサルアプリケーションとSPAのどちらで作るかを聞かれます。今回はSPAにします

? Deployment target: (Use arrow keys)
❯ Server (Node.js hosting)
  Static (Static/Jamstack hosting)

開発ターゲットを聞かれます。

? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◯ jsconfig.json (Recommended for VS Code if you're not using typescript)
 ◯ Semantic Pull Requests
 ◯ Dependabot (For auto-updating dependencies, GitHub only)

利用する開発ツールを聞かれます

? What is your GitHub username?

GitHubのユーザー名を聞かれます。gitに登録している場合は、登録名が自動で入ります。

? Version control system: (Use arrow keys)
❯ Git
  None

バージョン管理を行うか聞かれます。

⠴ Installing packages with npm
🎉  Successfully created project nuxt-todo-app

  To get started:

	cd nuxt-todo-app
	npm run dev

  To build & start for production:

	cd nuxt-todo-app
	npm run build
	npm run start

以上でNuxt.jsのインストールが完了しました。

Nuxt.jsの起動

それではNuxt.jsを起動してみます。先ほど作成したディレクトリに移動し、起動してみます。

cd nuxt-todo-app
npm run dev

上記を実行し http://localhost:3000 にアクセスすれば以下のような画面が表示されました。

Todoリストの作成

ディレクトリ構造は以下のようになっています。

.
├── README.md
├── components
├── node_modules
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
├── static
└── store

index.vue

作成したプロジェクトのpagesディレクトリにあるindex.vueファイルを開いて、以下のように編集します。

<template>
  <section class="container">
    <h1>Todo App</h1>
    <p><input type="text" name="content" v-model="content"  @focus="set_flg"/></p>
    <div>
      <button @click="insert">Save</button>
      <button @click="find">Find</button>
      <button @click="flag_reset">All</button>
    </div>
    <ul>
      <li v-for="(todo, index) in display_todos" :key="index">
        <span>{{ todo.content }}</span><span>({{ todo.created }})</span><button @click="remove(todo)">Done</button>
      </li>
    </ul>
  </section>
</template>

<script>
import {mapState} from 'vuex';

export default {
  data: function() {
    return {
      content: '',
      find_flg: false
    }
  },
  computed: {
    ...mapState(['todos']),
    display_todos: function() {
      if(this.find_flg) {
        var arr = [];
        var data = this.todos;
        data.forEach(element => {
          if(element.content.toLowerCase() == this.content.toLowerCase()) {
            arr.push(element);
          }
        });
        return arr;
      } else {
        return this.todos;
      }
    }
  },
  methods: {
    insert: function() {
      this.$store.commit('insert', {content: this.content});
      this.content = '';
    },
    find: function() {
      this.find_flg = true;
    },
    set_flg: function() {
      if(this.find_flg) {
        this.find_flg = false;
        this.content = '';
      }
    },
    remove: function(todo) {
      this.$store.commit('remove', todo)
    },
    flag_reset: function(){
      this.find_flg = false;
    }
  }
}
</script>

index.js

storeディレクトリにindex.jsを作成し処理を記述します。

import Vuex from 'vuex';

const createStore = () => {
    return new Vuex.Store({
        state: () => ({
            todos: [
            ]
        }),
        mutations: {
            insert: function(state, obj) {
                var d = new Date();
                var fmt = d.getFullYear()
                            + '-' + ('00' + (d.getMonth() + 1)).slice(-2)
                            + '-' + ('00' + d.getDate()).slice(-2)
                            + ' ' + ('00' + d.getHours()).slice(-2)
                            + ':' + ('00' + d.getMinutes()).slice(-2);
                state.todos.unshift({
                    content: obj.content,
                    created: fmt
                })
            },
            remove: function(state, obj) {
                for(let i = 0; i < state.todos.length; i++) {
                    const ob = state.todos[i];
                    if(ob.content == obj.content && ob.created == obj.created) {
                        alert('finished? ' + '"' + ob.content + '"');
                        state.todos.splice(i, 1);
                        return;
                    }
                }
            }
        }
    })
}

export default createStore

style.css

cssでスタイルを整えます。

.container {
    width: 400px;
    margin: 100px auto;
    text-align: center;
}

h1 {
    font-size: 32pt;
}

input {
    width: 300px;
    margin: 20px;
    padding: 8px 4px;
    font-size: 16pt;
}

button {
    margin: 0 10px;
    padding: 4px 8px;
    font-size: 10pt;
}

ul {
    margin-top: 20px;
    padding: 0;
    text-align: center;
}

li {
    list-style: none;
    margin: 5px 0;
    font-size: 14pt;
}

span {
    margin: 0 5px;
}

この記事を書いた人

TORAT 管理者

関連記事

Recommend愛されているブログ