iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
Modern Web

Vue.js 進階心法系列 第 28

後端說修改時只需要送「有修改的欄位」過來

今天來介紹一個,因為後端提出這個需求。要接 PATCH API 而產生的做法。

如果都是 PUT 就不用這麼做了。

要修改的地方

store/user/index.js

  • 加上一個 dirty 的物件,當作 「有改才有 key 值」的物件
  • 加上一個 mutation:userDirty 要給 dirty 用,因為要累計之前的修改,所以寫法和 user 不一樣
  • 加上同名的 getters: userDirty 要拿到 dirty
  • 加上一個 userForm 取得改 code 之前相同的結果,修改 user 時,沒修改的東西也包含在上面。

透過解構賦值的特性,後的 key 值會蓋掉前面的 key 值來做到,修改前後混合。
原本的 user 就只是拿來設定初值用的!

  • 設定初值時,要同步清掉 dirty
import actions from './actions';

export default {
  actions,
  state: {
    one: {},
    dirty: {},
    list: [],
  },
  mutations: {
    user (state, payload) {
      state.one = payload
      state.dirty = {}
    },
    userDirty (state, payload) {
      state.dirty = {
        ...state.dirty,
        payload
      }
    },
    users (state, payload) {
      state.list = payload
    }
  },
  getters: {
    user (state) {
      return state.one;
    },
    userDirty (state) {
      return state.dirty;
    },
    userForm (state) {
      return {
        ...state.one,
        ...state.dirty
      };
    },
    users (state) {
      return state.list;
    },
  },
};

store/user/actions.js

這樣要求的話,後端給的 API 應該是要指定成 PATCH 的唷!(不是的話請後端看一下 RESTful API)

import API from '@/utils/API';

export default {
  //...
  async updateClient({ getters }, { id }) {
    const res = await API.PATCH(`/clients/${id}`, getters.clientDirty);
    // ...
  }
  //...
};

components/UserForm.vue

這裡,是處理物件第一層 property 的那一層。
要改寫成「改什麼,物件就只帶什麼傳出去」。

原本的

$emit('update:first_name', {
  ...data,
  first_name: $event.target.value
})

改成這樣寫

$emit('update:first_name', {
  first_name: $event.target.value
})

整頁長這樣

只留下資料流相關的 code 其它先刪掉啦

  <form @submit.prevent="$emit('submit')">
    <label>first_name<br/>
      <input type="text"
        :value="data.first_name"
        @input="$emit('update:first_name', {
          first_name: $event.target.value
        })">
    </label><br/>
    <label>last_name<br/>
      <input type="text"
        :value="data.last_name"
        @input="$emit('update:last_name', {
          last_name: $event.target.value
        })">
    </label><br/>
    <label>email<br/>
      <input type="email"
        :value="data.email"
        @input="$emit('update:email', {
          email: $event.target.value
        })">
    </label><br/>
    <input type="submit" value="送出">
  </form>

src/views/UpdateUser.vue

資料流修改之後,比較重要的是 update 的頁面要改成編輯 userDirty 這個空物件。
將修改的內容累積在它身上

原本這樣

$store.commit('user', $event)

改成這樣

$store.commit('userDirty', $event)

引用時,就變這樣

  <UserForm
    :data="data"
    @update:first_name="$store.commit('userDirty', $event)"
    @update:last_name="$store.commit('userDirty', $event)"
    @update:email="$store.commit('userDirty', $event)"
    @submit="onSubmit"
  ></UserForm>

畫面 + 資料現況

原本這樣

我們來改一下名字 chris -> chriss

userDirty 就增加了一個值,增加了一個我們有修改才出現的值。
這時就算改回原本的,它也會存在唷!

這樣我們只要在 PUT 時傳送 userDirt。後端的需求是不是就滿足了呢?


上一篇
表單處理 Object 裡的 Array
下一篇
表格元件共用攻略
系列文
Vue.js 進階心法30

尚未有邦友留言

立即登入留言