以一個這樣的表單為例

  <UserForm
    :data="data"
    @update:firstName="$store.commit('user', $event)"
    @update:lastName="$store.commit('user', $event)"
    @update:email="$store.commit('user', $event)"
    @submit="onSubmit"
  ></UserForm>
data 會是以下面的 JSON 進行的設計
{
  firstName: '',
  lastName: '',
  email: ''
}
按照前一篇文章介紹的邏輯,我們可以自由的決定「哪個欄位不要有寫入的權限」
透過改變 event 的欄位,決定相對應的欄位 disabled (其實也有其它的做法)
如下圖的三種改變

v-model  <UserForm
    :data="data"
    @update:firstName="$store.commit('user', $event)"
    @update:lastName="$store.commit('user', $event)"
    @update:email="$store.commit('user', $event)"
    @submit="onSubmit"
  ></UserForm>
每一個 event 後面都是 $store.commit('user', $event) 這個是不是可以合併成相同的 event 反正後面接的語法都一樣,應該可以合併吧?而且 $event 用一個物件當輸入、用物件當輸出,怎麼不用 v-model 就好了?
  <UserForm
    :value="data"
    @input="$store.commit('user', $event)"
    @submit="onSubmit"
  ></UserForm>
可以,其實可以裡面只要這樣寫,就可以用 :value + @input = v-model
每個 input 都這樣 @input="$emit('update:user') 觸動相同的 event 就可以做成 v-model
  <UserForm
    v-model="data"
    @submit="onSubmit"
  ></UserForm>
src/components/UserForm.vue
component 裡面可以這樣實現 v-model 的做法
<input type="text"
  :disabled="!$listeners['input']"
  :value="value.firstName"
  @input="$emit('input', {
    ...value,
    firstName: $event.target.value
})">
<input type="text"
  :disabled="!$listeners['input']"
  :value="value.lastName"
  @input="$emit('input', {
    ...value,
    lastName: $event.target.value
})">
<input type="email"
  :disabled="!$listeners['input']"
  :value="value.email"
  @input="$emit('input', {
    ...value,
    email: $event.target.value
})">
缺點:
如果,不要物件進,物件出,而是讓各別的 event 吐出各別的值,那不就更接近原本的 form 表單控制?
src/components/UserForm.vue
那麼 component 裡面要這樣寫,就直覺多了。
<input type="text"
  :disabled="!$listeners['update:firstName']"
  :value="data.firstName"
  @input="$emit('update:firstName', $event.target.value">
<input type="text"
  :disabled="!$listeners['update:lastName']"
  :value="data.lastName"
  @input="$emit('update:lastName', $event.target.value">
<input type="email"
  :disabled="!$listeners['update:email']"
  :value="data.email"
  @input="$emit('update:email', $event.target.value">
外面就得這樣用,將組出新 object 的責任放在外面,並且要用 immutable 的做法將 mutation 裡的值換掉,以確保會更新畫面。
  <UserForm
    :data="data"
    @update:firstName="$store.commit('user', {
      ...data, firstName: $event })"
    @update:lastName="$store.commit('user', {
      ...data, lastName: $event })"
    @update:email="$store.commit('user', {
      ...data, email: $event })"
    @submit="onSubmit"
  ></UserForm>
優點: 可以個別的控製各個欄位的讀寫權限
缺點: 使用表單時,要猜一下這次拿到的 $event 是什麼。或者要印出來看一下才可以確定
以補習班記口訣的方式來教學的,表單的 component 的設計,把握下列幾個重點。
原因在於,想要在 component 裡面控制各別的欄位寫入 JSON,並且傳出組好的新物件,也就不用在後面的資料流判斷這個欄位是屬於哪個物件,這種多餘的判斷或資料動態分流的邏輯。
<input type="text"
  :disabled="!$listeners['update:firstName']"
  :value="data.firstName"
  @input="$emit('update:firstName', {
    ...data,
    firstName: $event.target.value
})">
<input type="text"
  :disabled="!$listeners['update:lastName']"
  :value="data.lastName"
  @input="$emit('update:lastName', {
    ...data,
    lastName: $event.target.value
})">
<input type="email"
  :disabled="!$listeners['update:email']"
  :value="data.email"
  @input="$emit('update:email', {
    ...data,
    email: $event.target.value
})">