[Express+Vue 搭建電商網站] 10 用 vue 建立一個表單

用 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 主要接收父組件傳來的三個參數 modelmanufacturersisEditing
然後在 methods 定義了一個方法 saveProduct,當使用者填完送出後按下送出會觸發這個方法。而在 saveProduct 內部調用了一個 save-product 方法,這個方法稍後會在父組件建立。除了調用父組件方法,在送出的同事還會把 this.model 內容傳遞給父組件。

template 部分

淺而易見的 template 就是一個表單,其中的 submit 事件使用 @submit.prevent 禁用預設的送出行為,並使用 saveProduct 替換。

接著寫了好幾個 class="form-group" 的區塊,代表要填寫的商品資料。其中前兩個區塊使用了 v-model 綁定 model 的 nameprice 兩個屬性;第三個區塊先對 select 標籤雙向綁定了 model.manufacturer 屬性,代表在內部做的行為都會影響對應的 model.manufacturer

接著使用迴圈把 script 中接收到的父組件 manufacturers 資料一個一個設為 option 標籤內容,並且把個別設定 manufacturer 的屬性,以及如果 model.manufacturer._id 和當前的 manufacturer._id 一致就把 selected 屬性設為 true

接著第四個 form-group 開始,依然是使用 v-model 綁定 model.imagemodel.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 中定義了 modelmanufacturersmethods 中定義了 addProduct 方法,並且綁定成 @save-product="saveProduct" 事件傳遞給子組件使用
儲存之後,重新開啟前端網頁,進入新建商品的頁面就可以看到子組件已經被加入 New.vue 的畫面上
new-product-page
目前為止我們學會了

  • 使用 vue-router 進行多頁面的跳轉與路由
  • 使用嵌套路由有組織的管理前端路由
  • 基礎的 Vue 使用
  • 學會建立 Vue 的組件並在父組件中使用

留言