Todoリスト #2
前回のviewからvueの機能を追加して完成させましょう。
リストを表示する
Todoリストの表示を行なっていきましょう
前回は
<ul> <li> <span>Todo1</span> <button>Return</button> <button>Delete</button> </li> <li> <span>Todo2</span> <button>Return</button> <button>Delete</button> </li> <li> <span>Todo3</span> <button>Return</button> <button>Delete</button> </li> </ul>
上記のcodeをv-forを使用したcodeに変えていきましょう
そのためにApp.vueからComplete.vueにリストを渡しましょう。
<div> <p>imcomplete</p> <div> <Incomplete :list="imcompleteList" /> </div> </div>
そしてdataにimcompleteListを定義しましょう
data() { return { imcompleteList: [] }; }
受け取る側
props: { list: { type: Array, default: () => [] } },
そしてtemplate側で
<ul> <li v-for="(item, i) in list" :key="i"> <span>{{ item }}</span> <button>Return</button> <button>Delete</button> </li> </ul>
とします
仮にlistに
['Todo1', 'Todo2', 'Todo3']
となっていた場合はv-forにて
<ul> <li> <span>Todo1</span> <button>Return</button> <button>Delete</button> </li> <li> <span>Todo2</span> <button>Return</button> <button>Delete</button> </li> <li> <span>Todo3</span> <button>Return</button> <button>Delete</button> </li> </ul>
な結果となります
li配下をループして各中身をitem, indexをiとしてます
こちらをIncomplete, Complete両方に適応させましょう。
- dataの配列は別々にしてtemplate側でも渡す値を別にしましょう script
data() { return { imcompleteList: [], completeList: [] }; }
template
<div> <p>complete</p> <div> <Complete :list="completeList" /> </div> </div>
Inputで入力した値を反映させる
今のままだと、inputに入力した値はどこにも反映されません。
なので入力した値を反映させます
inputタグにはv-modelを利用することによりscript側で値を取得することができます。
<input v-model="todo" type="text">
script側にも
data() { return { todo: "", imcompleteList: [], completeList: [] }; },
次にAdd Todoボタンを押したら、入力した値をimcompleteListに追加しましょう
template側のボタンではv-on:clickもしくは@clickを使用して、ボタンをclickした時を検知します
<button @click="addTodo">Add Todo</button>
この時にaddTodoというのはscript側に定義してあります。
methods: { addTodo() { this.imcompleteList.push(this.todo); // reset this.todo = ""; } }
this.todoというのはdata内のtodoのことです
imcompleteListに追加した後にtodoをリセットすることによりinput内の入力された値を消してます
imcompleteListに追加したことにより、Incompleteが再描画されて追加されているかと思います
imcompleteListを完了に持っていく
Completeボタンを押したら対象のTodoをCompleteに移動させます
まずはCompleteボタンを押したら発火するmethodを作成しましょう
<li v-for="(item, i) in list" :key="i"> <span>{{ item }}</span> <button @click="completeTodo(i)">Complete</button> <button>Delete</button> </li>
script
methods: { completeTodo(i) { this.$emit("complete", i); }, }
emitという新しいものが出てきました
emitは子コンポーネントから親コンポーネントに対して、eventを送ることができます
親コンポーネントであるApp.vueをこのようにしてみましょう
<Incomplete :list="imcompleteList" @complete="completeTodo" />
script
methods: { completeTodo(i) { // 対象のTodoを取得 const todo = this.imcompleteList[i]; // 対象のTodoをcompleteListに追加 this.completeList.push(todo); // imcompleteListから対象のTodoを削除 this.imcompleteList.splice(i, 1); }, }
emitの第1引数にevent名, そのあとは引数を入れることができます
こちら同じ要領でComplete TodoからImcomplete Todoに移してみましょう
Todoを削除する
最後に削除機能を追加します
今までのことを活かしてみましょう
Deleteボタンを押した際に発火するmethodを定義します
<li v-for="(item, i) in list" :key="i"> <span>{{ item }}</span> <button @click="imcompleteTodo(i)">Return</button> <button @click="deleteTodo(i)">Delete</button> </li>
script
methods: { deleteTodo(i) { this.$emit("delete", "complete", i); } }
App側で受け取る記述をしましょう
<Complete :list="completeList" @imcomplete="imcompleteTodo" @delete="deleteTodo"/>
script
methods: { deleteTodo(type, i) { if (type === "imcomplete") { this.imcompleteList.splice(i, 1); } else if (type === "complete") { this.completeList.splice(i, 1); } } }
以上である程度の機能は作れたかと思います。
サンプルはこちらになります