[Express+Vue 搭建電商網站] 20 重構後的頁面功能恢復
使用 Express + Vue 搭建一個電商網站 - 重構後的頁面功能恢復
要是你跟老闆說:現在我們專案的畫面好看了,但是功能全壞了
老闆應該會一臉問號問你在講什麼?
廢話不多說,趕快來修好上一篇中被我們弄壞的功能!
修復雙向綁定的問題
上一篇中有提過 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
中,就來看看發生什麼事情了吧
應該都還記得,商品的物件的製造商包含了 id
和 name
屬性
但是我們的下拉選單的 value
只有傳回 name
而後端資料庫要求製造商物件必須也要有 id
屬性
所以在送出時使用了 find
方法找到了對應 name
的製造商物件
並且將 modelData
中的製造商物件覆蓋掉,這樣就符合後端資料庫的要求了!
專案範例程式碼 GitHub 網址:ray247k/mini-E-commerce