搭配昨天的雙向綁定的學習以及之前所學的內容,製作一個簡單活動報名表單。
目標:可以讓使用者輸入姓名、電話、email以及選擇(複選)想要參加的活動。
<template>
<div>
<label for="name">姓名:</label>
<input type="text" id="name" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" required>
</div>
</template>
<script>
export default {
props: ['modelValue'],
computed: {
name: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
}
};
</script>
<template>
<div>
<label for="phone">電話:</label>
<input type="tel" id="phone" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" required>
</div>
</template>
<script>
export default {
props: ['modelValue'],
computed: {
phone: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
}
};
</script>
<template>
<div>
<label for="email">Email:</label>
<input type="email" id="email" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" required>
</div>
</template>
<script>
export default {
props: ['modelValue'],
computed: {
email: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
}
};
</script>
<template>
<div>
<label>選擇報名活動:</label>
<input type="checkbox" value="游泳" v-model="localValue"> 游泳
<input type="checkbox" value="羽球" v-model="localValue"> 羽球
<input type="checkbox" value="排球" v-model="localValue"> 排球
<input type="checkbox" value="籃球" v-model="localValue"> 籃球
<input type="checkbox" value="腳踏車" v-model="localValue"> 腳踏車
</div>
</template>
<script>
export default {
props: ['modelValue'],
data() {
return {
localValue: this.modelValue
};
},
computed: {
activity: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
},
watch: {
localValue(newValue) {
this.$emit('update:modelValue', newValue);
}
}
};
</script>
<template>
<form @submit.prevent="submitForm">
<h1>活動報名</h1>
<NameInput v-model="formData.name"></NameInput>
<PhoneInput v-model="formData.phone"></PhoneInput>
<EmailInput v-model="formData.email"></EmailInput>
<ActivityInput v-model="formData.activity" @update:modelValue="updateActivity"></ActivityInput>
<button type="submit">提交</button>
</form>
<div v-if="isSubmitted">
<h2>已報名信息:</h2>
<p>姓名: {{ formData.name }}</p>
<p>Email: {{ formData.email }}</p>
<p>電話: {{ formData.phone }}</p>
<p>報名活動: {{ formData.activity.join(', ') }}</p>
</div>
</template>
<script>
import NameInput from './NameInput.vue';
import PhoneInput from './PhoneInput.vue';
import EmailInput from './EmailInput.vue';
import ActivityInput from './ActivityInput.vue';
export default {
data() {
return {
formData: {
name: '',
phone: '',
email: '',
activity: []
},
isSubmitted: false
};
},
methods: {
submitForm() {
alert('報名成功!');
this.isSubmitted = true;
},
updateActivity(newValue) {
this.formData.activity = newValue;
}
},
components: {
NameInput,
PhoneInput,
EmailInput,
ActivityInput
}
};
</script>
<div id="app">
<event-registration></event-registration>
</div>
<script>
var app = Vue.createApp({});
var vm = app.mount('#app');
import EventRegistration from './EventRegistration.vue';
app.component('event-registration', EventRegistration);
app.mount('#app');
</script>
說明:
子元件:
姓名:
接受一個名字為modelValue的prop,用來顯示當前的姓名值,並通過@input事件將輸入的新值傳送給父元件。
computed:裡面有get和set方法。當讀取name屬性時,get方法會回傳modelValue的值,而當更新name屬性時,set方法會觸發update:modelValue事件,將新的值傳遞給父元件,這樣就達成了雙向綁定。
電話:同姓名元件
Email:同性名元件
活動選項:
大部分同姓名元件,但它還有一個watch來監聽本地值的變化,並將編化傳遞給父元件。這樣做是因為複選的選定狀態(選中或取消選中)不會直接更新到 modelValue中。而是會在localValue中進行追蹤。
父元件(主活動報名EventRegistration):
把主活動報名(EventRegistration)設定成父元件,裡面有一個表單(formData),其中有四個子元件:NameInput、PhoneInput、EmailInput 和 ActivityInput,還有一個isSubmitted,用來確認表單使否提交。
使用methods裡的submitForm方法提交表單,如果提交,對話框顯示"成功",並把isSubmitted設為true。
updateActivity方法則是用來從ActivityInput元件接收更新的資料,並且存到formData.activity。
使用v-model綁定formData裡的資料,並用v-if判斷,如果有提交,就顯示、更新對應的資料。報名活動的顯示、更新為formData.activity.join(', '),意思是因為我們選項是用陣列儲存,若要把陣列中的字串連在一起,就可以用join來加入,而","是將每組字串分開來,更容易閱讀。