商城-商品管理-商品新增
5.商品新增
5.1.效果预览
新增商品窗口:
这个表单比较复杂,因为商品的信息比较多,分成了4个部分来填写:
- 基本信息
- 商品描述信息
- 规格参数信息
- SKU信息
5.2.从0开始
我们刚刚在查询时,已经实现创建了MyGoodsForm.vue,并且已经在MyGoods中引入。
不过目前没有写代码:
<template>
<v-card>
my goods form
</v-card>
</template>
<script>
export default {
name: "my-goods-form",
props: {
oldGoods: {
type: Object
},
isEdit: {
type: Boolean,
default: false
}
},
data() {
return {
}
},
methods: {
}
}
</script>
<style scoped>
</style>
然后在MyBrand中,已经引入了MyGoodsForm组件,并且页面中也形成了对话框:
// 导入自定义的表单组件
import MyGoodsForm from './MyGoodsForm'
<v-dialog max-width="500" v-model="show" persistent>
<v-card>
<!--对话框的标题-->
<v-toolbar dense dark color="primary">
<v-toolbar-title>{
{isEdit ? '修改' : '新增'}}商品</v-toolbar-title>
<v-spacer/>
<!--关闭窗口的按钮-->
<v-btn icon @click="closeWindow">
<v-icon>close</v-icon>
</v-btn>
</v-toolbar>
<!--对话框的内容,表单-->
<v-card-text class="px-5">
<my-goods-form :oldGoods="oldGoods"/>
</v-card-text>
</v-card>
</v-dialog>
并且也已经给新增按钮绑定了点击事件:
<v-btn color="primary" @click="addGoods">新增商品</v-btn>
addGoods方法中,设置对话框的show属性为true:
addGoods() {
// 修改标记
this.isEdit = false;
// 控制弹窗可见:
this.show = true;
// 把oldBrand变为null
this.oldBrand = null;
}
不过弹窗中没有任何数据:
5.3.新增商品页的基本框架
5.3.1.Steppers,步骤线
预览效果图中,分四个步骤显示商品表单的组件,叫做stepper,看下文档:
其基本结构如图:
一个步骤线(v-stepper)总的分为两部分:
- v-stepper-header:代表步骤的头部进度条,只能有一个
- v-stepper-step:代表进度条的每一个步骤,可以有多个
- v-stepper-items:代表当前步骤下的内容组,只能有一个,内部有stepper-content
- v-stepper-content:代表每一步骤的页面内容,可以有多个
v-stepper
- value:其值是当前所在的步骤索引,可以用来控制步骤切换
- dark:是否使用黑暗色调,默认false
- non-linear:是否启用非线性步骤,用户不用按顺序切换,而是可以调到任意步骤,默认false
- vertical:是否垂直显示步骤线,默认是false,即水平显示
v-stepper-header的属性:
- 无
v-stepper-step的属性
- color:颜色
- complete:当前步骤是否已经完成,布尔值
- editable:是否可编辑任意步骤(非线性步骤)
- step:步骤索引
v-stepper-items
- 无
v-stepper-content
- step:步骤索引,需要与v-stepper-step中的对应
5.3.2.编写页面
首先我们在data中定义一个变量,记录当前的步骤数:
data() {
return {
step: 1, // 当前的步骤数,默认为1
}
},
然后在模板页面中引入步骤线:
<v-stepper v-model="step">
<v-stepper-header>
<v-stepper-step :complete="step > 1" step="1">基本信息</v-stepper-step>
<v-divider/>
<v-stepper-step :complete="step > 2" step="2">商品描述</v-stepper-step>
<v-divider/>
<v-stepper-step :complete="step > 3" step="3">规格参数</v-stepper-step>
<v-divider/>
<v-stepper-step step="4">SKU属性</v-stepper-step>
</v-stepper-header>
<v-stepper-items>
<v-stepper-content step="1">
基本信息
</v-stepper-content>
<v-stepper-content step="2">
商品描述
</v-stepper-content>
<v-stepper-content step="3">
规格参数
</v-stepper-content>
<v-stepper-content step="4">
SKU属性
</v-stepper-content>
</v-stepper-items>
</v-stepper>
效果:
步骤线出现了!
那么问题来了:该如何让这几个步骤切换呢?
5.3.3.步骤切换按钮
分析
如果改变step的值与指定的步骤索引一致,就可以实现步骤切换了:
因此,我们需要定义两个按钮,点击后修改step的值,让步骤前进或后退。
那么这两个按钮放哪里?
如果放在MyGoodsForm内,当表单内容过多时,按钮会被挤压到屏幕最下方,不够友好。最好是能够悬停状态。
所以,按钮必须放到MyGoods组件中,也就是父组件。
父组件的对话框是一个card,card组件提供了一个滚动效果,scrollable,如果为true,card的内容滚动时,其头部和底部是可以静止的。
现在card的头部是弹框的标题,card的中间就是表单内容。如果我们把按钮放到底部,就可以实现悬停效果。
页面添加按钮
改造MyGoods的对话框组件:
查看页面:
添加点击事件
现在这两个按钮点击后没有任何反应。我们需要给他们绑定点击事件,来修改MyGoodsForm中的step的值。
也就是说,父组件要修改子组件的属性状态。想到什么了?
props属性。
我们先在父组件定义一个step属性:
然后在点击事件中修改它:
previous(){
if(this.step > 1){
this.step--
}
},
next(){
if(this.step < 4){
this.step++
}
}
页面绑定事件:
<!--底部按钮,用来操作步骤线-->
<v-card-actions class="elevation-10">
<v-flex class="xs3 mx-auto">
<v-btn @click="previous" color="primary" :disabled="step === 1">上一步</v-btn>
<v-btn @click="next" color="primary" :disabled="step === 4">下一步</v-btn>
</v-flex>
</v-card-actions>
然后把step属性传递给子组件:
<!--对话框的内容,表单-->
<v-card-text class="px-3" style="height: 600px">
<my-goods-form :oldGoods="oldGoods" :step="step"/>
</v-card-text>
子组件中接收属性:
测试效果:
5.4.商品基本信息
商品基本信息,主要是一些纯文本比较简单的SPU属性,例如:
商品分类、商品品牌、商品标题、商品卖点(子标题),包装清单,售后服务
接下来,我们一一添加这些表单项。
注:这里为了简化,我们就不进行form表单校验了。之前已经讲过。
5.4.1.在data中定义Goods属性
首先,我们需要定义一个goods对象,包括商品的上述属性。
data() {
return {
goods:{
categories:{
}, // 商品3级分类数组信息
brandId: 0,// 品牌id信息
title: '',// 标题
subTitle: '',// 子标题
spuDetail: {
packingList: '',// 包装列表
afterService: '',// 售后服务
},
}
}
注意,这里我们在goods中定义了spuDetail属性,然后把包装列表和售后服务作为它的属性,这样符合数据库的结构。
5.4.2.商品分类选框
商品分类选框之前我们已经做过了。是级联选框。直接拿来用:
<v-cascader
url="/item/category/list"
required
showAllLevels
v-model="goods.categories"
label="请选择商品分类"/>
跟以前使用有一些区别:
- 一个商品只能有一个分类,所以这里去掉了multiple属性
- 商品SPU中要保存3级商品分类,因此我们这里需要选择showAllLevels属性,显示所有3级分类
效果:
查看goods的属性,三级类目都在:
5.4.3.品牌选择
select组件
品牌不分级别,使用普通下拉选框即可。我们查看官方文档的下拉选框说明:
组件名:v-select
比较重要的一些属性:
- item-text:选项中用来展示的字段名,默认是text
- item-value:选项中用来作为value值的字段名,默认是value
- items:待选项的对象数组
- label:提示文本
- multiple:是否支持多选,默认是false
其它次要属性:
- autocomplete:是否根据用户输入的文本进行搜索过滤(自动),默认false
- chips:是否以小纸片方式显示用户选中的项,默认false
- clearable:是否添加清空选项图标,默认是false
- color:颜色
- dense:是否压缩选择框高度,默认false
- editable:是否可编辑,默认false
- hide-details:是否隐藏错误提示,默认false
- hide-selected:是否在菜单中隐藏已选择的项
- hint:提示文本
- 其它基本与
v-text-filed
组件类似,不再一一列举
页面实现
备选项items需要我们去后台查询,而且必须是在用户选择商品分类后去查询。
我们定义一个属性,保存品牌的待选项信息:
然后编写一个watch,监控goods.categories的变化:
watch: {
'goods.categories': {
deep: true,
handler(val) {
// 判断商品分类是否存在,存在才查询
if (val && val.length > <