表單與響應式狀態
在 Vue 中,表單元件通常透過 `v-model` 與響應式狀態雙向綁定:
- 使用者修改表單 → 狀態同步更新
- 狀態修改 → 表單畫面同步更新
Vue 3 常見做法是使用 `reactive()` 管理整個表單物件,或使用多個 `ref()` 管理個別欄位。
## 各類表單元件
### 1. 單行輸入框
```vue
<input v-model="form.username" type="text" />
```
等同於:
```vue
<input
:value="form.username"
@input="form.username = $event.target.value"
/>
```
也可以使用修飾詞:
```vue
<input v-model.trim="form.username" />
```
`trim` 會自動移除前後空白。
---
### 2. 下拉式選單
```vue
<select v-model="form.country">
<option value="">請選擇國家</option>
<option value="tw">台灣</option>
<option value="jp">日本</option>
</select>
```
選取的 `option` 值會同步到 `form.country`。
如果需要數字型別,可以使用 `.number`:
```vue
<select v-model.number="form.age">
<option :value="18">18 歲</option>
<option :value="20">20 歲</option>
</select>
```
---
### 3. 勾選框
#### 單一勾選框:布林值
```vue
<input v-model="form.agree" type="checkbox" />
```
勾選時:
```js
form.agree === true
```
取消勾選時:
```js
form.agree === false
```
#### 多個勾選框:陣列
```vue
<input v-model="form.skills" value="vue" type="checkbox" />
<input v-model="form.skills" value="react" type="checkbox" />
```
如果使用者勾選 Vue 和 React,狀態會是:
```js
form.skills // ['vue', 'react']
```
---
## 整合範例
以下範例包含:
- 單行輸入框:姓名
- 下拉式選單:國家
- 單一勾選框:同意服務條款
- 多個勾選框:擅長技能
```vue
<script setup>
import { reactive, computed } from 'vue'
const form = reactive({
username: '',
country: '',
agree: false,
skills: []
})
const canSubmit = computed(() => {
return (
form.username.trim() !== '' &&
form.country !== '' &&
form.agree
)
})
function submitForm() {
if (!canSubmit.value) {
alert('請完整填寫表單')
return
}
console.log('送出的資料:', {
username: form.username,
country: form.country,
agree: form.agree,
skills: form.skills
})
alert('表單送出成功')
}
</script>
<template>
<form @submit.prevent="submitForm">
<!-- 單行輸入框 -->
<div>
<label for="username">姓名:</label>
<input
id="username"
v-model.trim="form.username"
type="text"
placeholder="請輸入姓名"
/>
</div>
<!-- 下拉式選單 -->
<div>
<label for="country">國家:</label>
<select id="country" v-model="form.country">
<option value="">請選擇</option>
<option value="tw">台灣</option>
<option value="jp">日本</option>
<option value="us">美國</option>
</select>
</div>
<!-- 單一勾選框 -->
<div>
<label>
<input v-model="form.agree" type="checkbox" />
我同意服務條款
</label>
</div>
<!-- 多個勾選框 -->
<fieldset>
<legend>擅長技能:</legend>
<label>
<input
v-model="form.skills"
type="checkbox"
value="Vue"
/>
Vue
</label>
<label>
<input
v-model="form.skills"
type="checkbox"
value="JavaScript"
/>
JavaScript
</label>
<label>
<input
v-model="form.skills"
type="checkbox"
value="CSS"
/>
CSS
</label>
</fieldset>
<button type="submit" :disabled="!canSubmit">
送出
</button>
</form>
<hr />
<h3>目前表單狀態</h3>
<pre>{{ form }}</pre>
</template>
```
### 重點
1. `reactive()` 適合集中管理整個表單狀態。
2. `v-model` 會依照元件類型自動處理:
- `input[type="text"]`:字串
- `select`:選取的值
- 單一 `checkbox`:布林值
- 多個同名或同 `v-model` 的 `checkbox`:陣列
3. `@submit.prevent` 可避免表單送出時重新整理頁面。
4. `computed` 可根據目前表單狀態,決定是否允許送出。
相關學習地圖、教學課程
F2E 網站前端工程