今天來看看一個常見問題。
{
first_name: 'chris',
last_name: 'wang',
email: 'chris@goodideas-studio.com'
camp: {
name: 'web camp',
member_count: 10
}
}
先依昨天講的 UserForm 的 component 可以這樣寫。
<form @submit.prevent="$emit('submit')">
<label>firstName<br/>
<input type="text"
:disabled="!$listeners['update:firstName']"
:value="data.firstName"
@input="$emit('update:firstName', {
...data,
firstName: $event.target.value
})">
</label><br/>
<label>lastName<br/>
<input type="text"
:disabled="!$listeners['update:lastName']"
:value="data.lastName"
@input="$emit('update:lastName', {
...data,
lastName: $event.target.value
})">
</label><br/>
<label>email<br/>
<input type="email"
:disabled="!$listeners['update:email']"
:value="data.email"
@input="$emit('update:email', {
...data,
email: $event.target.value
})">
</label><br/>
<pre>camp: {{data.camp}}</pre>
<input type="submit" value="送出">
</form>
畫面
還有一個 camp
怎麼辦呢?
{
// ....
camp: {
name: 'web camp',
member_count: 10
}
}
也就是以這樣的視角看待它
{
name: 'web camp',
member_count: 10
}
有一個 camp 的視角時,依昨天教的,是不是就可以這樣做
<div class="camp-fields">
<div class="camp-fields">
<label>
name<br />
<input
type="text"
:disabled="!$listeners['update:name']"
:value="data.name"
@input="
$emit('update:name', {
...data,
name: $event.target.value,
})
"
/>
</label><br />
<label>
member_count<br />
<input
type="number"
:disabled="!$listeners['update:member_count']"
:value="data.member_count.toString()"
@input="
$emit('update:member_count', {
...data,
member_count: Number($event.target.value),
})
"
/>
</label><br />
</div>
</div>
在此,還對 type="number"
的欄位做了轉態,將資料保持在數字型別。但是顯示時要轉型別,從數字變成字串。
<form @submit.prevent="$emit('submit')">
<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
})">
<camp-form
:data="data.camp"
@update:name="$emit('update:camp', {
...data,
camp: $event
})"
@update:member_count="$emit('update:camp', {
...data,
camp: $event
})"
></camp-form>
<input type="submit" value="送出">
</form>
並且在 UserForm 上面加上新的 event @update:camp="$store.commit('user', $event)"
表示在此會修改 camp 這個屬性。
<UserForm
:data="data"
@update:firstName="$store.commit('user', $event)"
@update:lastName="$store.commit('user', $event)"
@update:email="$store.commit('user', $event)"
@update:camp="$store.commit('user', $event)"
@submit="onSubmit"
></UserForm>
為方便抓到重點,我把不必要的 type="text"
先拿掉,因為它是預設值,也把 disabled
拿掉因為要不要這個屬性,是看需求,不是設計的重點。(只是符合需求時,這樣做很符合語意)
<input
:value="data.firstName"
@input="$emit('update:firstName', {
...data,
firstName: $event.target.value
})"
>
跟下面的 form
做一個對比。
<camp-form
:data="data.camp"
@update:name="$emit('update:camp', {
...data,
camp: $event
})"
@update:member_count="$emit('update:camp', {
...data,
camp: $event
})"
></camp-form>
兩個都是為了處理 user 的屬性,而使用的 component。
輸入
:value
將值輸入 component:data
將物件輸入 component輸出
@input
表示更新這個值,並將值輸出 component@update:property
表示物件更新某個屬性,並將物件輸入 component所以
在 input 的輸入中,:value="data.firstName"
輸出就是取得 firstName 的新值。
在 camp-form 的輸入中 :data="data.camp"
輸出就是取得 user.camp 的新值。
兩件事情的更新層次一致之後,按照這樣的觀念實作,任何巢狀式的物件,就不用害怕它的表單有多複雜了。
對應方式也許不是一對一,但是可以限縮在一個合理的有限範圍之內,像是表單控制項與資料型別之間的關係,也有著一定的合理範圍之內。
有了昨天的學習心得。今天做出這樣的結果是不是就快速許多了呢?