寫后臺商品頁面的思路
1、分析功能需求
管理商品必須要實現(xiàn)的幾個功能
- 1、展示所有商品
- 2、添加商品
- 3、修改商品
2、分析數(shù)據(jù)結(jié)構(gòu)
先看一下數(shù)據(jù)結(jié)構(gòu)
首先商品分類

類下面的商品詳情

3、 實現(xiàn)功能步驟
思路:
1、將添加商品類,添加商品,修改商品分離成單獨的組件

2、添加路由


3、 先寫出添加商品頁面
掛在路由打開mangerprods.vue
<template>
<section class="box">
<div class="head">
<h3>{{this.$route.name}}</h3>
</div>
<!-- 商品管理路由 -->
<div class="prodmenu">\
<el-menu
mode="horizontal"
:default-active="$router.path"
router>
<el-menu-item
v-for="item in $router.options.routes[1].children[1].children"
:key="item.path"
:index="item.path">
{{item.name}}
</el-menu-item>
</el-menu>
</div>
<!-- 渲染路由 -->
<router-view></router-view>
</section>
</template>
<script>
export default {
// ..
}
</script>
<style lang="less" scoped>
@import '../../common/less/index.less';
.box {
.head {
.leftborder
}
.prodmenu {
margin: 0 15px;
}
}
</style>
4、寫添加商品類別頁面
<template>
<!-- 添加商品類 -->
<div class="addprod">
<h4>添加一個商品類</h4>
<el-input
placeholder="請輸入商品類名"
v-model="prodtype"
clearable>
</el-input>
<el-input
placeholder="請輸入商品類簡介"
v-model="prodsub"
type="textarea"
:rows="2"
clearable>
</el-input>
<el-button type="danger" :disabled="disabled" @click="addtype" round>添加</el-button>
</div>
</template>
<script>
export default {
data () {
return {
prodtype: '',
prodsub: ''
}
},
computed: {
disabled () {
if (this.prodtype === '' || this.prodsub === '') {
return true
} else {
return false
}
}
},
methods: {
addtype () {
console.log('do')
}
}
}
</script>
<style lang="less" scoped>
@import '../../../common/less/index.less';
.addprod {
.learncontent;
.el-input {
margin: 5px 0;
}
.el-button {
margin: 10px 0;
width: 100%;
}
}
</style>
5、寫添加商品頁面
<template>
<!-- 新增商品 -->
<div class="addprod">
<h4>新增商品</h4>
<el-form ref="addprod" :rules="prodrules" :model="addprod" label-width="80px">
<el-form-item label="商品名" prop="name">
<el-input v-model="addprod.name" placeholder="請輸入商品名"></el-input>
</el-form-item>
<el-form-item label="價格" prop="price">
<el-input v-model.number="addprod.price" placeholder="請輸入商品價格"></el-input>
</el-form-item>
<el-form-item label="商品主圖" prop="image">
<el-upload
class="prod-image"
action="/learn/upload"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<img v-if="imageUrl" :src="imageUrl" class="cur-image">
<i v-else class="el-icon-plus prod-uploader-icon"></i>
</el-upload>
</el-form-item>
<el-form-item label="商品類別" prop="type">
<el-select v-model="addprod.type" placeholder="請選擇商品類別">
<el-option label="石榴" value="shiliu"></el-option>
<el-option label="火腿" value="ham"></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否上架">
<el-switch v-model="addprod.selling"></el-switch>
</el-form-item>
<el-form-item label="商品簡介" prop="desc">
<el-input type="textarea" v-model="addprod.desc" placeholder="請請輸入商品簡介"></el-input>
</el-form-item>
<el-form-item label="商品詳情" prop="info">
<mavon-editor ref="md" @imgAdd="$imgAdd" @imgDel="$imgDel" v-model="addprod.info"></mavon-editor>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="newprod">立即添加</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {UploadFile} from '../../../api/api'
export default {
data () {
return {
imageUrl: '',
addprod: {
name: '',
price: '',
type: '',
selling: '',
desc: '',
info: ''
},
prodrules: {
name: [
{
required: true,
message: '請輸入商品名',
trigger: 'blur'
},
{
min: 3,
max: 15,
message: '長度在 3 到 15 個字',
trigger: 'blur'
}
],
price: [
{
required: true,
message: '請輸入商品價格',
trigger: 'blur'
},
{
type: 'number',
message: '價格必須是數(shù)字',
trigger: 'blur'
}
],
type: [
{
required: true,
message: '商品必須選擇一個類別',
trigger: 'change'
}
],
desc: [
{
required: true,
message: '請輸入商品簡介',
trigger: 'blur'
}
]
}
}
},
methods: {
newprod () {
this.$refs.addprod.validate(valid => {
if (valid) {
// console.log('add prod!')
// const prodFd = new FormData()
// prodFd.append('name', this.addprod.name)
} else {
console.log('請先完成驗證')
return false
}
})
},
// mavoneditor圖片上傳并替換地址
// 綁定@imgAdd event
$imgAdd (pos, $file) {
// 第一步.將圖片上傳到服務(wù)器.
let formdata = new FormData()
formdata.append('file', $file)
UploadFile(formdata)
.then(url => {
// console.log(url)
console.log(this.addprod.info)
// 第二步.將返回的url替換到文本原位置 -> 
this.$refs.md.$img2Url(pos, url.data)
})
},
$imgDel (pos) {
delete this.img_file[pos]
},
// 獲取商品主圖上傳成功后返回的圖片
handleSuccess (res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
// 商品主圖再上傳前對文件進行判斷
beforeUpload (file) {
const isPIC = file.type === 'image/jpeg' || 'image/png'
const isLt5M = file.size / 1024 / 1024 < 5
if (!isPIC) {
this.$message.error('上傳圖片只能是 JPG或PNG 格式!')
}
if (!isLt5M) {
this.$message.error('上傳圖片大小不能超過 5MB!')
}
return isPIC && isLt5M
}
}
}
</script>
<style lang="less" scoped>
@import '../../../common/less/index.less';
.addprod {
.learncontent;
.el-form {
text-align: left;
.el-select {
width: 100%;
}
.el-switch {
margin: 10px 0 0 0;
}
.prod-image {
width: 200px;
height: 200px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
.cur-image {
width: 100%;
}
.prod-uploader-icon {
font-size: 45px;
color: #8c939d;
width: 200px;
height: 200px;
line-height: 200px;
text-align: center;
}
}
}
}
</style>
6、引入markdown編輯器
cnpm i mavon-editor --save
引用
main.js

使用
再addprod.vue中直接使用
引用mavoneditor

mavonedior上傳圖片操作

與服務(wù)端進行交互的API

因為markdown編輯器是具有實時預(yù)覽功能,如果我們將本地圖片插入,執(zhí)行步驟是這樣的
1、他會立即執(zhí)行上傳圖片操作,并獲取服務(wù)端返回的圖片地址
2、獲取到圖片地址,mavon會立刻向服務(wù)端請求這個地址來獲取這張圖片,并渲染出來
- 7 寫服務(wù)端代碼


4、測試效果

效果是合適的

同時后端也記錄了3次上傳和3次獲取圖片
5、遇見的坑
我當時寫服務(wù)端代碼的時候,再上傳圖片的地方,我將
const form = new formidable.IncomingForm()
寫在了頁面的開頭,并沒有將formidable的實例化卸載每一次上傳的過程中,這導(dǎo)致了一個問題,上傳第一張圖片可以成功,但上傳第二張開始就發(fā)生錯誤
Can't set headers after they are sent
這是因為我所有的req解析都在同一個實例化的form里面,第一次執(zhí)行upload成功時,form會調(diào)用一次form.on('end'),第二次upload成功時,form也會調(diào)用一次form.on('end'),這樣就產(chǎn)生了Can't set headers after they are sent這個錯誤
6、感謝segmentfault的 @程序猿小卡_casper
再此非常感謝segmentfault的 @程序猿小卡_casper,無私的幫助我解決了問題并細心的講解錯誤原因,謝謝!!,同時也感謝其他真心幫助我解決問題的朋友!
又興趣的朋友可以看看這個問題的原題
用nodejs的formidable上傳圖片,第一張上傳成功,再上傳發(fā)生錯誤Can't set headers after they are sent
https://segmentfault.com/q/1010000012722383
7 、github地址:
learn:https://github.com/lyttonlee/learn
server:https://github.com/lyttonlee/express-server-for-learn