覺得 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 吧