商品管理之三级联动静态组件
先做俩个卡片组件,分开距离
三级联动很多地方都用到了它,我们可以封装成一个组件
注册为一个全局组件
<div><el-form :inline="true" class="demo-form-inline"><el-form-item label="一级分类"><el-select placeholder="请选择" value=""><el-option label="区域一" value="shanghai"></el-option><el-option label="区域二" value="beijing"></el-option></el-select></el-form-item><el-form-item label="二级分类"><el-select placeholder="请选择" value=""><el-option label="区域一" value="shanghai"></el-option><el-option label="区域二" value="beijing"></el-option></el-select></el-form-item><el-form-item label="三级分类"><el-select placeholder="请选择" value=""><el-option label="区域一" value="shanghai"></el-option><el-option label="区域二" value="beijing"></el-option></el-select></el-form-item>
</el-form></div>
商品管理之三级联动动态组件
书写相对于的api
拿到数据,然后渲染到页面上
一级分类完成
我们需要在一级联动数据发生改变的时候,把id传给二级联动。这里有一个注意点,就是这个是在组件中,@change这个其实就是自定义事件
绑定事件,但是报错了
接口测试没有问题,后面查询出来是接口的请求写错了
三级联动完成
一级分类数据发送变化的时候,二级,三级分类数据要变化。首先要清除原有的值,同时我们需要在子组件中给父组件传递参数
<template><div><!-- inline:代表的是行内表单,代表一行可以放置多个表单元素 --><el-form :inline="true" class="demo-form-inline" :model="cForm"><el-form-item label="一级分类"><el-selectplaceholder="请选择"v-model="cForm.category1Id"@change="handler1":disabled="show"><el-option:label="c1.name":value="c1.id"v-for="(c1, index) in list1":key="c1.id"></el-option></el-select></el-form-item><el-form-item label="二级分类"><el-selectplaceholder="请选择"v-model="cForm.category2Id"@change="handler2":disabled="show"><el-option:label="c2.name":value="c2.id"v-for="(c2, index) in list2":key="c2.id"></el-option></el-select></el-form-item><el-form-item label="三级分类"><el-selectplaceholder="请选择"v-model="cForm.category3Id"@change="handler3":disabled="show"><el-option:label="c3.name":value="c3.id"v-for="(c3, index) in list3":key="c3.id"></el-option></el-select></el-form-item></el-form></div>
</template><script>
export default {name: "CategorySelect",props: ["show"],data() {return {//一级分类的数据list1: [],//二级分类的数据list2: [],//三级分类的数据list3: [],//收集相应的一级二级三级分类的idcForm: {category1Id: "",category2Id: "",category3Id: "",},};},//组件挂载完毕:向服务器发请求,获取相应的一级分类的数据mounted() {//获取一级分类的数据的方法this.getCategory1List();},methods: {//获取一级分类数据的方法async getCategory1List() {//获取一级分类的请求:不需要携带参数let result = await this.$Api.attr.reqCategory1List();if (result.code == 200) {this.list1 = result.data;}},//一级分类的select事件回调(当一级分类的option发生变化的时候获取相应二级分类的数据)async handler1() {//清除数据this.list2 = [];this.list3 = [];this.cForm.category2Id = "";this.cForm.category3Id = "";//解构出一级分类的idconst { category1Id } = this.cForm;this.$emit("getCategoryId", { categoryId: category1Id, level: 1 });//通过一级分类的id,获取二级分类的数据let result = await this.$Api.attr.reqCategory2List(category1Id);if (result.code == 200) {this.list2 = result.data;}},//二级分类的select事件回调(当二级分类的option发生变化的时候获取相应三级分类的数据)async handler2() {//清除数据this.list3 = [];this.cForm.category3Id = "";//结构出数据const { category2Id } = this.cForm;this.$emit("getCategoryId", { categoryId: category2Id, level: 2 });let result = await this.$Api.attr.reqCategory3List(category2Id);if (result.code == 200) {this.list3 = result.data;}},//三级分类的事件回调handler3() {//获取三级分类的idconst { category3Id } = this.cForm;this.$emit("getCategoryId", { categoryId: category3Id, level: 3 });},},
};
</script><style scoped>
</style>
父组件来接收数据
平台属性管理动态展示属性
就是三级联动数据确定那一刻,获取平台属性的内容
先写接口
拿到数据
动态渲染
平台属性之添加属性与修改属性静态完成
通过一个v-show来控制这个显示和隐藏
这里有一个细节,那就是没有选一二三级。这个按钮就不能使用。这里我们用 :disabled="!category3Id" 如果有category3Id就是相当于可以使用
我们还需要写添加属性修改属性的结构
<div v-show="!isShowTable"><el-form :inline="true" ref="form" label-width="80px" ><el-form-item label="属性名"><el-input placeholder="请输入属性名"></el-input></el-form-item></el-form><el-button type="primary" icon="el-icon-plus">添加属性值</el-button><el-button @click="isShowTable = true">取消</el-button><el-table style="width: 100%; margin: 20px 0px" border ><el-table-column align="center" type="index" label="序号" width="80"> </el-table-column><el-table-column width="width" prop="prop" label="属性值名称"></el-table-column><el-table-column width="width" prop="prop" label="操作"></el-table-column></el-table><el-button type="primary">保存</el-button><el-button @click="isShowTable = true">取消</el-button></div></el-card></div>
收集属性名和属性值操作
这里要说一下什么是属性和属性值
这块写属性名称 属性列表
属性:颜色
属性值:粉色,红色等等
调用这个接口
携带参数有讲究的
"attrName": "string","attrValueList": [{"attrId": 0,"id": 0,"valueName": "string"}],"categoryId": 0,"categoryLevel": 0,"id": 0
注意:别在data当中收集三级分类的id
因为对象存储数据是无序存储
就是你不能确定对象中的属性谁先谁后,因此这个this.category3Id就是undefined
通过这种方式就能获取到表单的属性
现在我们获取到了属性名,但是没有获取到属性值
async getAttrList() {//获取分类的IDconst { category1Id, category2Id, category3Id } = this;//获取属性列表的数据let result = await this.$Api.attr.reqAttrList(category1Id,category2Id,category3Id);if (result.code == 200) {this.attrList = result.data;}}, addAttrValue() {//向属性值的数组里面添加元素//attrId:是你相应的属性的id,目前而言我们是添加属性的操作,还没有相应的属性的id,目前而言带给服务器的id为undefined//valueName:相应的属性值的名称this.attrInfo.attrValueList.push({attrId: this.attrInfo.id, //对于修改某一个属性的时候,可以在已有的属性值基础之上新增新的属性值(新增属性值的时候,需要把已有的属性的id带上)valueName: "",flag: true,});}
解决返回按钮数据回显问题
就是在每次按钮点击之前,把之前的数据清空。
同时我们这里可以点击添加属性按钮,收集到3id
addAttr() {//切换table显示与隐藏this.isShowTable = false;//清除数据//收集三级分类的idthis.attrInfo = {attrName: "", //属性名attrValueList: [//属性值,因为属性值可以有多个因此用数组,每一个属性值都是一个对象需要attrId,valueName],categoryId: this.category3Id, //三级分类的idcategoryLevel: 3, //因为服务器也需要区分几级id};},
修改属性操作
这个row就是这一行的属性值
这里有一个bug,就是我们点击取消按钮的时候他也会变化。这里我们不能使用浅拷贝,由于数据结构当中存在对象里面套数组,数组里面有套对象,因此需要使用深拷贝解决这类问题
这里可以使用插件loadsh进行深拷贝,这就不能实现值不会随的v-model的修改,而修改了
查看模式与修改模式切换
当我们点击添加属性值按钮的时候就应该把属性的id传进去
对于修改某一个属性的时候,可以在已有的属性值基础之上新增新的属性值(新增属性值的时候,需要把已有的属性的id带上)
input跟span来回进行切换
参看模式:显示span
编辑模式:显示input
注意:通过flag标记进行切换参看模式与编辑模式,但是需要注意的时候,一个属性flag是没有办法控制全部属性的切换
解决方案就是在每个元素添加的时候给他添加一个属性flag
flag属性:给每一个属性值添加一个标记flag,用户切换查看模式与编辑模式,好处,每一个属性值可以控制自己的模式切换
当前flag属性,响应式数据(数据变化视图跟着变化)
然后通过v-if来控制 当失去焦点和回车的时候,我们需要进行模式的切换
查看模式与编辑模式注意事项
1.如果属性值为空不能作为新的属性值,需要给用户提示,让他输入一个其他的属性值
2.新增的属性值不能与已有的属性值重复
row最新新增的属性值【数组的最后一项元素】 而item是指得这个数组的每一项
修改查看模式和编辑模式的切换
就是我们切换到编辑模式上,发现flag是没有的,因为它是后面添加上的,并不是响应式数据
可以通过这种方式,但是视图并不会跟着变化(对象中后追加的属性,Vue默认不做响应式处理)
这里我们需要使用$set
第一个参数:对象 第二个参数:添加新的响应式属性 第三参数:新的属性的属性值
表单元素自动对焦实现
点击span的时候,获取到input的节点,然后自动对焦
这里我们给span绑定一个事件 同时给input 用ref获取到它的节点,但是这个input并不是一个而是多个。因此我们可以用索引值当做它的标记 用于区分它是第几个信息
获取input节点,实现自动聚焦
需要注意:点击span的时候,切换为input变为编辑模式,但是需要注意,对于浏览器而言,页面重绘与重拍耗时间的
点击span的时候,重绘重拍一个input它是需要耗费事件,因此我们不可能一点击span立马获取到input
$nextTick,当节点渲染完毕了,会执行一次
除了切换span要获取聚焦外,点击添加属性值按钮也应该让获取到数组的最后一项聚焦
删除属性值的操作
这里我们需要用到这个组件
复制到代码中,结构大概是这样的
这里使用模板字符串的方式,告诉用户删除的是那个 confirm是气泡确定框确定事件
但是我们会发现调用这个办法是没有效果的,因为我们这个项目的版本是老版本很旧
所以用@onConfirm
保存操作
用这个接口
这里提交给服务器的参数,有俩个讲究
整理参数:1,如果用户添加很多属性值,且属性值为空的不应该提交给服务器
2.提交给服务器数据当中不应该出现flag字段
用filter这个方法实现那flag这个属性过滤掉
按钮与三级联动的可操作性
isShowTable给子传过去
子接收show属性
然后通过这个属性来控制