覺得 update 算是 todo 裡面比較複雜的地方。
因為需要切換成有輸入框的修改模式
。
<template>
<div class="container">
<h1>vue & vuex Todo List example</h1>
<hr>
<div class="row">
<div class="input-group col-md-4">
<input
type="text"
class="form-control"
placeholder="add Todo.."
v-model="newTodo"
@keyup.enter="actionAddTodo" />
<span class="input-group-btn">
<button class="btn btn-success" type="button" @click="actionAddTodo">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</button>
</span>
</div>
</div>
<!-- 左右兩個欄位分別存放 todo / done -->
<div class="row">
<div class="col-md-6">
<h2>Todo List:</h2>
<ol>
<todoItem v-for="(item, index) in todoList" :item="item" />
</ol>
</div>
<div class="col-md-6">
<h2>Done List:</h2>
<ol >
<li v-for="(item, index) in doneList">
<label>
<input
type="checkbox"
:checked="item.done"
@change="toggleTodo( item.key )">
{{ item.content }}
</label>
</li>
</ol>
</div>
</div><!-- end row -->
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import todoItem from '../components/todo-item.vue';
export default {
components: {
todoItem
},
data () {
return {
newTodo: ''
}
},
computed: mapGetters({
todoList: 'getTodo',
doneList: 'getDone',
}),
methods: {
...mapActions([
'toggleTodo',
'deleteTodo',
]),
actionAddTodo () {
this.$store.dispatch('addTodo', this.newTodo);
this.newTodo = '';
}
}
}
</script>
因為需要切換兩種狀態,因此需要有紀錄這個數據的地方。
可是這個數據不太需要紀錄在 vuex 裡面,
也不可能紀錄在 page 的 data 裡面。
有 100 todo 怎麼辦?
所以包裝成一個 component 利用每個封閉的 data 獨自去紀錄,
而 component 本身只需要接收父層傳遞 todo object 單一資料既可。
<template>
<li>
<div v-if="!updateMode">
<label>
<input
type="checkbox"
:checked="item.done"
@change="toggleTodo( item.key )">
{{ item.content }}
</label>
<!-- 新增切換修改按鈕 -->
<button class="btn btn-xs btn-primary" @click="showEditMode">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
</button>
<button class="btn btn-xs btn-danger" @click="deleteTodo( item.key )">
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</button>
</div>
<div v-if="updateMode" >
<input
class="edit-input"
v-focus="updateMode"
placeholder="edit Todo.."
:value="item.content"
@keyup.enter="actionEdit"
@blur="cancelEdit"
@keyup.esc="cancelEdit"/>
</div>
</li>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
export default {
props: {
item: Object
},
data () {
return {
updateMode: false // 修改模式預設值
}
},
/*
此 directives 是參考作者的 code
主要功能是切換模式之後 focus input 功能
value 為 updateMode
$nextTick 功能是:上個動作完成後,才執行裡面包含的程式。
之後會寫一篇關於自訂:Vue Directive
*/
directives: {
focus (el, { value }, { context }) {
if (value) {
context.$nextTick(() => {
el.focus();
})
}
}
},
methods: {
...mapActions([
'toggleTodo',
'deleteTodo',
'updateTodo'
]),
showEditMode () {
this.updateMode = true;
},
actionEdit (e) {
const userChange = e.target.value.trim();
console.log('userChange', this.item.key, userChange);
this.updateTodo({
key: this.item.key,
change: userChange
});
this.updateMode = false;
},
cancelEdit (e) {
e.target.value = this.item.title;
this.updateMode = false;
}
}
}
</script>
<style>
.edit-input{
line-height: 1em;
}
</style>
游標離開
與按下 esc
的時候取消修改
使用者點到了其他地方或者按下 ESC 想取消修改,因此必須把 input 的 value 修改回去,不然下次打開會是上次未修改成功的值。
export const updateTodo = ({ commit }, obj) => {
console.log('updateTodo', obj);
commit(types.UPDATE_TODO, obj);
}
// 更新
[types.UPDATE_TODO] (state, obj) {
for(var i in state.todos){
var item = state.todos[i];
if ( item.key === obj.key){
console.log('UPDATE_TODO:', item.content, ' to →', obj.change);
// 找到 todo 更新 content
state.todos[ i ].content = obj.change;
break;
}
}
},
Todo list 簡單範例就到這邊。
實作小範例入門 Vue & Vuex 2.0 - github 完整範例
使用 git checkout 切換每天範例。
感謝大大 精彩教學
以下有兩個錯誤
1.metutions.js -> 應為 mutations.js
2.mutations.js 中的 接收物件屬性 應為 obj.change 不是 obj.update
:)
感謝 LeoYeh 大大精闢的指正,太感謝了!!
立即修正文章內容。
Esc取消時
e.target.value = this.item.title;
應該是 e.target.value = this.item.content;
是content 不是 title 吧