用 vue 建立一個表單
後端的 API 上次已經開了出來,接著來建立前端使用的表單。
這次的目標是建立新增商品時所用的表單,會使用到基本的 Vue 知識,如果沒看過文件的可以先了解一下官方文件。
架構規劃
之前我們建立了 /src/views/admin/New.vue
這個模板做為網址 /admin/new
的顯示頁面。
在這節中會建立一個表單,然後讓他作為頁面組件顯示在 New.vue
中
程式實作
建立一個新的檔案 /src/components/products/ProductForm.vue
作為表單的組件,可以看到我們在這邊的存放位置不再是 /src/views/
因為他是組件,就該好好的放在「components」內是比較好的架構方式
<template>
<form @submit.prevent="saveProduct">
<div class="col-lg-5 col-md-5 col-sm-12 col-xs-12">
<div class="form-group">
<label>Name</label>
<input type="text" placeholder="Name" v-model="model.name" name="name" class="form-control" />
</div>
<div class="form-group">
<label>Price</label>
<input
type="number"
class="form-control"
placeholder="Price"
v-model="model.price"
name="price"
/>
</div>
<div class="form-group">
<label>Manufacturer</label>
<select type="text" class="form-control" v-model="model.manufacturer" name="manufacturer">
<template v-for="manufacturer in manufacturers">
<option
:key="manufacturer._id"
:value="manufacturer._id"
:selected="manufacturer._id == (model.manufacturer && model.manufacturer._id)"
>{{manufacturer.name}}</option>
</template>
</select>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
<div class="form-group">
<label>Image</label>
<input
type="text"
lass="form-control"
placeholder="Image"
v-model="model.image"
name="image"
class="form-control"
/>
</div>
<div class="form-group">
<label>Description</label>
<textarea
class="form-control"
placeholder="Description"
rows="5"
v-model="model.description"
name="description"
></textarea>
</div>
<div class="form-group new-button">
<button class="button">
<i class="fa fa-pencil"></i>
<!-- Conditional rendering for input text -->
<span v-if="isEditing">Update Product</span>
<span v-else>Add Product</span>
</button>
</div>
</div>
</form>
</template>
<script>
export default {
props: ["model", "manufacturers", "isEditing"],
methods: {
saveProduct() {
this.$emit("save-product", this.model);
}
}
};
</script>
程式說明
於是我們來看看這段看起來很長很嚇人的東西在做什麼?
分為兩部分來理解
script 部分
props
主要接收父組件傳來的三個參數 model
、manufacturers
、isEditing
然後在 methods
定義了一個方法 saveProduct
,當使用者填完送出後按下送出會觸發這個方法。而在 saveProduct
內部調用了一個 save-product
方法,這個方法稍後會在父組件建立。除了調用父組件方法,在送出的同事還會把 this.model
內容傳遞給父組件。
template 部分
淺而易見的 template
就是一個表單,其中的 submit
事件使用 @submit.prevent
禁用預設的送出行為,並使用 saveProduct
替換。
接著寫了好幾個 class="form-group"
的區塊,代表要填寫的商品資料。其中前兩個區塊使用了 v-model
綁定 model 的 name
、price
兩個屬性;第三個區塊先對 select
標籤雙向綁定了 model.manufacturer
屬性,代表在內部做的行為都會影響對應的 model.manufacturer
。
接著使用迴圈把 script 中接收到的父組件 manufacturers
資料一個一個設為 option
標籤內容,並且把個別設定 manufacturer
的屬性,以及如果 model.manufacturer._id
和當前的 manufacturer._id
一致就把 selected
屬性設為 true
接著第四個 form-group
開始,依然是使用 v-model
綁定 model.image
和 model.description
屬性。最後一個 form-group
使用 v-if
判斷式來判斷 isEditing
來渲染不同的按鈕文字
完成了子組件之後,就要引入父組件內。所以重新打開 New.vue
這個檔案,引入剛剛建立的表單組件
<template>
<product-form
@save-product="addProduct"
:model="model"
:manufacturers="manufacturers"
>
</product-form>
</template>
<script>
import ProductForm from '@/components/products/ProductForm.vue';
export default {
data() {
return {
model: {},
manufacturers: [
{
_id: 'sam',
name: 'Samsung',
},
{
_id: 'apple',
name: 'Apple',
},
],
};
},
methods: {
addProduct(model) {
console.log('model', model);
},
},
components: {
'product-form': ProductForm
}
}
</script>
當要在一個組件中使用另一個組件時,需要在父組件的 components
中註冊。在我們的 New.vue
中就將 ProductForm
註冊為 product-form
,於是我們就可以在 <template>
區塊中使用 <product-form />
來使用組件。
同時在 data
中定義了 model
和 manufacturers
;methods
中定義了 addProduct
方法,並且綁定成 @save-product="saveProduct"
事件傳遞給子組件使用
儲存之後,重新開啟前端網頁,進入新建商品的頁面就可以看到子組件已經被加入 New.vue
的畫面上
目前為止我們學會了
- 使用 vue-router 進行多頁面的跳轉與路由
- 使用嵌套路由有組織的管理前端路由
- 基礎的 Vue 使用
- 學會建立 Vue 的組件並在父組件中使用
留言
張貼留言