Help us understand the problem. What is going on with this article?

【Nuxt.js】todoアプリを作成してみた②

前回の記事はこちら
https://qiita.com/ayapon/items/d93807e7699434279531

作成の手順

(1)Nuxt.jsのプロジェクト作成
(2)template作成
(3)store作成
(4)追加機能作成
(5)検索機能作成
(6)削除機能作成
(7)cssファイル作成

今回は(4)以降について書きます。

(4)追加機能作成

methodsにinsertを追加し、入力されたtodoをstoreの中にある配列todosに追加します。

pages/index.vue
<template>
  <section class="container">
    <h1>Todo App</h1>
    <p><input type="text" name="content" v-model="content" /></p>
    <div>
      <button @click="insert">save</button>
      <button>find</button>
    </div>
    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        <span>{{ todo.content }}</span><span>({{ todo.created }})</span><span>×</span>
      </li>
    </ul>
  </section>
</template>

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

export default {
  data: function() {
    return {
      content: ''
    }
  },
  computed: {
    ...mapState(['todos'])
  },
  methods: {
    insert: function() {
      this.$store.commit('insert', {content: this.content});
      this.content = '';
    }
  }
}
</script>

まず、inputタグにv-modelを追加し、入力されたtodoとdataのcontentをデータバインディングします。
そのあと、saveボタンにクリックイベントを設定して、methodsのinsertを呼び出します。
methodsのinsertでは、storeのmutationsのinsertに、引数として入力されたtodoを渡して実行します。
また、todoを追加したら入力欄は空欄になるようにcontentを空にします。

todoを入力→saveボタンを押すと、todoが追加されていると思います。
(4)sample.png

(5)検索機能作成

検索機能を作成するにあたって、dataにfind_flgを追加します。
そして、find_flgがtrueの場合は検索した結果を、
find_flgがfalseの場合はtodosすべてを表示するように修正します。

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>
    </div>
    <ul>
      <li v-for="(todo, index) in display_todos" :key="index">
        <span>{{ todo.content }}</span><span>({{ todo.created }})</span><span>×</span>
      </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 = '';
      }
    },
  }
}
</script>

findボタンにクリックイベントを設定してmethodsのfindを呼び出し、
findボタンが押されたらfind_flgをtrueにします。
そして、computedにdisplay_todosを設定し、find_flgがtrueの場合は新たにarrという配列を用意し、
入力されたtodoがtodosの中にあればarrに追加して、最終的にarrを返します。
find_flgがfalseの場合はtodosすべてを返すようにします。
また、templateのlistの部分もtodos→display_todosに修正します。

これで一通り検索機能はできていますが、検索結果が表示されているとき(find_flgがtrueのとき)に
入力欄にクリックしたら検索を終了してtodosすべてを表示するように、
inputタグの中にfocusを設定してset_flgを呼び出し、find_flgをfalseにするようにします。

「hogehoge」と入力→findボタンを押して、hogehogeのみ表示されていたらOKです。
また、検索結果が表示されている状態で入力欄をクリックすると、
すべてのtodosが表示されることが確認できると思います。

(6)削除機能作成

削除機能はmethodsにremoveを追加します。

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>
    </div>
    <ul>
      <li v-for="(todo, index) in display_todos" :key="index">
        <span>{{ todo.content }}</span><span>({{ todo.created }})</span><span @click="remove(todo)">×</span>
      </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)
    }
  }
}
</script>

表示されているtodoそれぞれについている「×」の部分にクリックイベントを設定し、
methodsのremoveを呼び出します。その際、クリックされたtodoを引数として渡します。
methodsのremoveでは、storeのmutationsのremoveに、引数としてクリックされたtodoを渡して実行します。

×を押してクリックすると、「remove (クリックされたtodoの内容)」とアラートが表示され、
クリックされたtodoが削除されると思います。

(7)cssファイル作成

cssファイル作成はおまけです。
Nuxt.jsでcssファイルを読み込む方法を書いておきます。

pagesフォルダにstyle.cssを作成し、以下のようにコードを書きます。

pages/style.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;
}

そして、sample-todo-appフォルダ直下にあるnuxt.config.jsのcssの部分を、以下のように修正します。

nuxt.config.js
  /*
  ** Global CSS
  */
  css: [
    'pages/style.css'
  ]

これでcssファイルが反映されていると思います。

おわりに

引き続きNuxt.jsの勉強がんばりたいです。
初めて記事を書いたので、もし間違った記載などあればご指摘いただけると幸いです。

参考

Vue.js & Nuxt.js超入門

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away