[Express+Vue 搭建電商網站] 20 頁面功能恢復

20 頁面功能恢復

頁面功能恢復

要是你跟老闆說:現在我們專案的畫面好看了,但是功能全壞了
老闆應該會一臉問號問你在講什麼?廢話不多說,趕快來修好上一篇中被我們弄壞的功能!

修復雙向綁定的問題

上一篇中有提過 element-ui 的輸入組件不接受 v-model 的功能。所以為了雙向綁定資料,我們需要利用其他方法

Edit 組件

首先打開 Edit 組件進行修復

<template>
 <div>
 <div class="title">
 <h1>This is Admin/Edit</h1>
 </div>
 <product-form
 @save-product="updateProduct"
 :model="model"
 :manufacturers="manufacturers"
 :isEditing="true"
 ></product-form>
 </div>
</template>
<script>
import ProductForm from "@/components/products/ProductForm.vue";
export default {
 created() {
 const { name = "" } = this.modelData || {};
 if (!name) {
 this.$store.dispatch("productById", {
 productId: this.$route.params["id"]
 });
 }
 if (this.manufacturers.length === 0) {
 this.$store.dispatch("allManufacturers");
 }
 },
 computed: {
 manufacturers() {
 return this.$store.getters.allManufacturers;
 },
 model() {
 const product = this.$store.getters.productById(this.$route.params["id"]);
 const res = { ...product, manufacturer: { ...product.manufacturer } };
 return res;
 }
 },
 methods: {
 updateProduct(product) {
 this.$store.dispatch("updateProduct", {
 product
 });
 }
 },
 components: {
 "product-form": ProductForm
 }
};
</script>

這一步中我們又將 data 屬性中的 model 給恢復到了 computed 中,用來暫存 model 物件的資料提高效能。而雙向綁定的問題會在其中的 ProductForm 解決。

ProductForm 組件

我們來嘗試另一種方式修復雙向綁定,先看程式碼

<template>
 <div class="productInfo">
 <el-form class="form" ref="form" label-width="180px">
 <el-form-item label="Name">
 <el-input v-model="modelData.name"></el-input>
 </el-form-item>
 <el-form-item label="Price">
 <el-input v-model="modelData.price"></el-input>
 </el-form-item>
 <el-form-item label="Manufacturer ">
 <el-select v-model="modelData.manufacturer.name" clearable placeholder="請選擇製造商">
 <el-option
 v-for="manufacturer in manufacturers"
 :key="manufacturer._id"
 :label="manufacturer.name"
 :value="manufacturer.name"
 ></el-option>
 </el-select>
 </el-form-item>
 <el-form-item label="Image ">
 <el-input v-model="modelData.image"></el-input>
 </el-form-item>
 <el-form-item label="Description ">
 <el-input type="textarea" v-model="modelData.description"></el-input>
 </el-form-item>
 <el-form-item>
 <el-button v-if="isEditing" type="primary" @click="onSubmit">Update Product</el-button>
 <el-button v-else @click="onSubmit">Add Product</el-button>
 </el-form-item>
 </el-form>
 </div>
</template>
<script>
export default {
 data() {
 return {
 modelData: { manufacturer: { name: "" } }
 };
 },
 props: ["model", "manufacturers", "isEditing"],
 created() {
 const product = this.model;
 this.modelData = { ...product, manufacturer: { ...product.manufacturer } };
 },
 watch: {
 model(val) {
 this.modelData = val;
 }
 },
 methods: {
 onSubmit() {
 const manufacturer = this.manufacturers.find(
 item => item.name === this.modelData.manufacturer.name
 );
 this.modelData.manufacturer = manufacturer;
 this.$emit("save-product", this.modelData);
 }
 }
};
</script>
<style>
.productInfo {
 padding-top: 10px;
}
.form {
 margin: 0 auto;
 width: 500px;
}
.el-input__inner {
 height: 60px;
}
</style>

在上面的程式中,不直接使用父組件的 model 作為表單的資料物件,而是在目前的組件中自訂一個新的 modelData 物件。
並且在組件剛被建立時就先從父組件取得 modle 物件,暫定為 product。然後將 product 需要用到的屬性解構給 modelData 物件。
這樣就避免了表單物件操作 computed,但這只解決了一半問題,說好的雙向綁定呢?
所以我們要透過監測組件的變化,利用 watch 方法監測使用者輸入,並且將新的資料儲存到 modelData 物件中,這樣就完成雙向綁定啦!而且表單也可以隨意編輯。

商品資訊表單錯誤問題

當修改或是新建表單時,會看到錯誤的提示訊息:id 屬性未定義。因為錯誤訊息說是在 ProductForm 中,就來看看發生什麼事情了吧

應該都還記得,商品的物件的製造商包含了 idname 屬性,但是我們的下拉選單的 value 只有傳回 name,而後端資料庫要求製造商物件必須也要有 id 屬性。
所以在送出時使用了 find 方法找到了對應 name 的製造商物件,並且將 modelData 中的製造商物件覆蓋掉,這樣就符合後端資料庫的要求了!

留言