雙擊修改資料內容

STEP 1:新增雙擊事件

在原本呈現資料的地方加上 雙擊事件 @dblclick
雙擊後會觸發事件 editTodo(item) 並會傳物件進來

<li
  class="list-group-item"
  v-for="(item, key) in filteredTodos"
  @dblclick="editTodo(item)"
></li>

同樣在 Vue app 也要加上 editTodo function

methods: {
    addTodo: function(){...},
    removeTodo: function(todo){...},

    // 加上 editTodo function
    editTodo: function(item){
      console.log(item);
    },

  },

雙擊後 console 會出現物件

STEP 2:切換顯示 input

建立 Cache

首先我們要把 item 存起來
因為我們要知道目前是哪一筆資料被編輯

因此我們先新增兩個 data
並把 item 存在 cacheTodo、把標題存在 cacheTitle

...
data: {
    newTodo: '',
    todos: [
      {
        id: '345',
        title: '妳好',
        completed: false,
      }
    ],
    visibility: 'all',

    // 新增兩個 data
    cacheTodo: {},
    cacheTitle: '',
  },
methods: {
    addTodo: function(){...},
    removeTodo: function(todo){...},

    // editTodo
    editTodo: function(item){
      console.log(item);
      this.cacheTodo = item;
      this.cacheTitle = item.title;
    },

cacheTitle 會拿來做 input 預設顯示的內容

動態切換 input 與資料內容

  1. 把 input 放到 div.d-flex 的下方
  2. 利用 v-if 新增顯示條件
    如果 item.id 不等於 cacheTodo.id 就顯示完整 li
    如果 item.id 等於 cacheTodo.id 就顯示 input
<li
  class="list-group-item"
  v-for="(item, key) in filteredTodos"
  @dblclick="editTodo(item)"
  v-if="item.id !== cacheTodo.id"
>
  <div class="d-flex">
    ...
  </div>
  <!-- 新增 input -->
  <input type="text" class="form-control" v-if="item.id === cacheTodo.id" />
</li>

現在點擊兩下就能切換到 input 了
不過目前一次只能顯示一個 input

因為 cacheTodo 預存的資料會被替換掉
所以一次只能呈現一筆資料內容

STEP 3 編輯資料內容

  1. input 綁定 cacheTitle 資料
  2. input 新增事件:按下 ESC 取消編輯
  3. input 新增事件:按下 Enter 完成編輯
<input
  type="text"
  class="form-control"
  v-if="item.id === cacheTodo.id"
  v-model="cacheTitle"
  @keyup.esc="cancelEdit"
  @keyup.enter="doneEdit(item)"
/>

取消編輯:this.cacheTodo 等於空物件
完成編輯:把預存的標題存成標題,然後把預存的標題清空,也把 cacheTodo 清空

methods: {
    addTodo: function(){...},
    removeTodo: function(todo){...},
    // 編輯的物件
    editTodo: function(item){
      console.log(item);
      this.cacheTodo = item;
      this.cacheTitle = item.title;
    },
    // 取消編輯
    cancelEdit: function(){
      this.cacheTodo = {};
    },
    // 完成編輯
    doneEdit: function(item){
      item.title = this.cacheTitle;
      this.cacheTodo = '';
      this.cacheTodo = {};
    }
},

計算還有幾筆待辦事項未完成

使用花括號呈現未完成的筆數於畫面上

<span>還有 {{ countLeftTodo }} 筆任務未完成</span>

計算方式的寫法與 filteredTodos 的部分有點相似

先宣告一個存放未完成 item 的陣列
然後將整個 todos 內容用 forEach 去跑

如果 item 的 completed 是 false,就把它放到 leftTodos 裡面
最後回傳 leftTodos 的長度
這個長度就是我們想呈現的未完成筆數了 :P

computed: {
    filteredTodos: function(){...},

    // 計算還有幾筆待辦事項未完成
    countLeftTodo: function(){
        let leftTodos = [];
        this.todos.forEach(function(item){
          if(!item.completed){
              leftTodos.push(item);
          }
        });
        return leftTodos.length;
    },
},

結語

到這邊 TodoList 就算是大功告成了!
經過這次 TodoList 的練習,算是大概瞭解一些 Vue.js 的概觀與優缺點
接下來在學習 Vue 的語法細節及生命週期時,就會更容易了解這些的相關性

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫