[VR 前後端交响曲Day28] Rails专案开发 - 删除ticket (使用vuex状态管理)

CRUD新增、删除、修改、显示功能是一个完整的线上系统不可或缺的功能。
昨天我们完成了更新 ticket,以及介绍了dispatch让Vue可以联络到Vuex的action,
今天就延续着介绍以Vue.js实作CRUD的删除功能!

Step 1. UI: 删除icon连动 deleteTicket method

我们移至ticket.vue这个ticket元件的档案,
起手式来先用个fontawesome加一个可爱的垃圾桶,并且v-on绑定click事件deleteTicket

<template>
  <div class="ticket">
    {{ ticket.name }}
    <div>
      <button class="edit-btn" @click="editTicket=true"><i class="fas fa-edit text-gray-400"></i></button>
      //垃圾桶在这
      <button class="delete-btn" @click="deleteTicket"><i class="fas fa-trash text-gray-400"></i></button>

      <div v-if="editTicket" class="edit-area">
        <i class="far fa-window-close edit-cancel" @click="cancelUpdate"></i> 
        <textarea type="text" class="edit-input" v-model="ticket.name"></textarea>
        <button class="update-ticket-btn" @click="updateTicket">更新</button>
      </div>

    </div>
  </div>
</template>

垃圾桶放完後,一边来点点看,一边思考如何撰写deleteTicketmethod

删除功能最重要的是要删到对的东西!因此,为了确定有抓对那笔即将被删除的ticket,先用console.log确认一下是不是正确的资料:

<script>
  export default {              
    name: 'Ticket',
    props: ["ticket"],
    data: function () {
      return {
      }
    },    
    methods: {
      deleteTicket(evt){
        event.preventDefault();
        if (confirm(`确定删除"${this.ticket.name}" 吗?`)){
          console.log("remove: ") 
          console.log(this.ticket.id)
          console.log(this.ticket.name)
        }

      }
    }
  }
</script>

Step2. 使用Vuex状态管理 this.$store.dispatch

昨天介绍了dispatch这个概念,让我们在Vue元件里可以呼叫到Vuex store instance中actions定义的方法。

请看目前程序码的架构,左边为Vue(ticket元件)、右边为Vuex store。

我想要当点击确认删除後,能够呼叫action中定义的deleteTicket方法,并且传入ticket_id和column_id两个参数。

2-1. 橘色框线:Vue元件里的methods despatch至Vuex的action

methods: {
  cancelUpdate(evt){
    //略
  },
  updateTicket(evt){
    //略
  },
  deleteTicket(evt){
    event.preventDefault();
    if (confirm(`确定删除"${this.ticket.name}" 吗?`)){
      this.$store.dispatch("deleteTicket", {ticket_id: this.ticket.id, column_id: this.ticket.column_id})                
    }
  }
}

2-2. 黄色框线:Vuex actions里的delete_column,呼叫mutations

确定删除ticket的路径及动词,再请Rails打ajax到後端。

Helper HTTP Verb Path Controller#Action
kanban_ticket_path DELETE /kanbans/:kanban_id/tickets/:id(.:format) tickets#destroy

成功删除资料库内的ticket之後,
我们发出一个commit,请求mutation里DELETE_TICKET重新前端渲染的资料,并带入刚刚从Vue元件传进来的ticket_id和column_id两个参数。

  actions: {
    updateTicket({ commit }, {id, name}){
      //略
    },
    deleteTicket({ commit }, {ticket_id, column_id}){
      let el = document.querySelector("#column");   
      Rails.ajax({
        url: `/kanbans/${el.dataset.kanbanid}/tickets/${ticket_id}`,
        type: 'DELETE',
        dataType: 'json',
        success: result => {
          commit("DELETE_TICKET", {ticket_id, column_id});
        },
        error: error => {
          console.log(error)
        }
      });
    },
    dragColumn({ commit, state }, evt) {
      //略
    },
    fetchColumn({ commit }, kanbanid){
      //略
    }
  }

2-3. 红色框线:Vuex mutations里的DELETE_TICKET

DELETE_TICKET:需要透过传进来的ticket_idcolumn_id,去比对state里的columns的index现在是第几栏和第几列,再透过splice把需要删掉的那张ticket从columns阵列中移除。

(PS. 比较mutations里的UPDATE_TICKET可以直接透过ticket实体去找自己的id以及reference的column_id,但DELETE_TICKET已经删除了ticket实体,因此我们要从外面的元件带进来column_id 和ticket_id来比对资料。)

  mutations: {
    UPDATE_COLUMNS(state, columns){
      state.columns = columns;
    },
    // Day 28
    DELETE_TICKET(state, {ticket_id, column_id}){      
      let column_index = state.columns.findIndex(col => col.id == column_id)
      let ticket_index = state.columns[column_index].tickets.findIndex(tkt => tkt.id == ticket_id)
      state.columns[column_index].tickets.splice(ticket_index, 1)
    },

    //Day 27
    UPDATE_TICKET(state, ticket){
      let column_index = state.columns.findIndex(col => col.id == ticket.column_id)
      let ticket_index = state.columns[column_index].tickets.findIndex(tkt => tkt.id == ticket.id)
      state.columns[column_index].tickets.splice(ticket_index, 1, ticket)
    }
  },

感想:原本以为CRUD里,删除总是那个最快可以做好的功能,但我昨天和今天大概花了10个小时才完全搞清楚个中原理,把握出vuex的流程、如何传参数、如何送commit给mutation~(以及解完自己产生的Bug 呜呜...)。当功能实作成功的那一刻,真的很感动!

透过mutations去更动前端虽然看起来有点绕(dispatch=> actions => mutations),但等到我们明天来实作Action cable,你就会发现好处多多~

敬请期待明天!


<<:  Day28 火堆实作 - 模组参数

>>:  Day28 - reversing.kr - Easy_ELF

DAY6 Figma Prototype

承昨天的Figma介绍,你试着靠自己的力量完成了一个设计稿,满心期待的拿给客户看...... 客户:...

【面试】coding interview

另一系列悲剧..不小心按到上一页.. 感觉这篇还少了点什麽? 如果平常只用过 Leetcode,建...

[Day17] Vue 3 单元测试 (Unit Testing) - Vue Test Utils + Jest 基本范例 & 核心语法

在开始进入复杂的内容之前,我想先带大家认识几个会大量出现在每一个测试程序码里的核心语法,这些语法如果...

Flutter学习Day1 dart&flutter安装(windows)

小弟弟第一次发文, 如有不好的地方 请多包涵 (≧∀≦)ゞ 由於我是vs code 使用爱好者 所以...

〖按图施工保证完工〗Linux CentOS 7 建置 Laradock

前言 看群里和laravel社群有些人对docker不太会使用,在这里我推荐使用laradock来部...