目录
1-分类三级列表
2-属性列表
2.1-需求功能分析
2.2-功能代码实现数据获取和变动
2.3-动态渲染数据
3-新增修改属性
3.1-点击新增属性逻辑处理
3.2-点击列表页面修改属性逻辑
3.3-新增和修改属性
3.4-点击删除属性值
3.5-点击删除属性
1-分类三级列表
需求:当我们点击菜单平台属性管理,我们需要跳转到平台属性页面,页面加载时候,需要获取一级分类的数据,当选择一个一级分类时,需要获取对应二级分类的数据,当选择一个二级分类时,需要获取对应三级分类的数据...并且改变一级分类时候,对应的二级,三级分类应该置空...
技术分析:我们观察发现三级分类联动需要在项目多个地方使用,所以我们可以将这个功能封装为一个全局组件;而且在组件加载的时候,我们需要向调用服务端接口,获取相关数据。
需要使用到行内表单:<el-form :inline="true" :model="formInline" class="demo-form-inline">
引入全局自定义组件
v-model只能收集value的属性值;所以value动态获取分类的id;因为需要分类id获取下一级的数据。
//获取一级分类数据接口 /admin/product/getCategory1 get
export const reqCategory1List = ()=>request({url:'/admin/product/getCategory1',method:'get'});
//获取二级分类数据接口 admin/product/getCategory2/{category1Id} get
export const reqCategory2List = (category1Id)=>request({url:`/admin/product/getCategory2/${category1Id}`,method:'get'});
//获取三级分类数据接口 /admin/product/getCategory3/{category2Id} get
export const reqCategory3List = (category2Id)=>request({url:`/admin/product/getCategory3/${category2Id}`,method:'get'});
2-属性列表
2.1-需求功能分析
当用户点击三级分类的时候,需要向服务器发起请求获取三级分类的属性数据,三级分类在全局组件中,需要将相关分类id传递给父组件,子父通信需要使用到自定义事件。当我们点击添加-修改 属性的时候,我们需要将三级分类置灰(disabled)不可更改状态,因为添加-修改 属性按钮在父组件中,点击时触发变量的变化需要传递给子组件,父子通信需要用到props属性。
2.2-功能代码实现数据获取和变动
先实现自定义事件,实现分类id改变来传递给父组件获取数据;这里需要优化点:每次变更了分类id,都需要将属性列表数据置空。核心代码:@getCategoryId="getCategoryId" :show="!isShowTable"。
一级分类id发生变化,想父组件通信,传递数据:this.$emit("getCategoryId", { categoryId: category1Id, level: 1 });level: 1表示一级分类发生变化(为了方便区分是哪个id发生变化),同理在handler2和handler3中需要分别添加
this.$emit("getCategoryId", { categoryId: category1Id, level: 2 }),this.$emit("getCategoryId", { categoryId: category1Id, level: 3 });
2.3-动态渲染数据
当获取到服务器数据后,我们需要动态展示服务器端数据。添加属性按钮只有当三级id有值的时候才可用,否则disabled;
3-新增修改属性
3.1-点击新增属性逻辑处理
当用户点击添加属性按钮时,需要隐藏之前展示的列表,显示新增属性名和属性值操作。
清除之前填写的属性数据(用户可能点击一次添加属性,然后点击取消,当我们再次点击添加属性需要清空attrName和attrValueList)
3.2-点击列表页面修改属性逻辑
当我们点击页面的修改按钮,需要把相关属性名称和属性值带过去,因为这里属性对象不是简单的对象,对象里面包含数组,数组里面又包含对象,不能使用浅拷贝this.attrInfo ={...row}来实现;而是需要深拷贝来实现,这里我们使用lodash当中的深拷贝this.attrInfo = cloneDeep(row)来实现。当我们修改某一个属性的时候,我们可以再新增属性值,此时需要在点击新增属性值按钮的时候,我们需要将当前的属性id赋值过去。
需求细节问题:当我们新增属性值的时候input的时候,我们可以编辑属性值,当我们的焦点失去或者按下键盘的enter键,我们需要将数据变为span;当我们再次点击的时候,我们需要再次变为input输入框,这里我们可以采用一个变量来标记。如果我们在data中定义标记位,那么添加多个属性的时候,会同时控制多行,这个时候我们需要在每个对象元素里面给一个标记位来控制,我们可以在新增对象属性的时候给对象添加一个字段flag,默认为true。v-if和v-else中间不能出现任何的div,否则失效。
点击修改的时候,需要将数据回显,数据复杂,需要深拷贝;为了实现在input和span之间进行切换,我们需要在元素上面新增一个flag属性,如果我们只是简单赋值(item.flag=false)就不是响应式属性(因为Vue无法探测普通的新增 property,这样书写的属性并非响应式属性),这个时候我们需要用到$set来实现
我们点击添加属性值的时候除了需要多设置一个flag变量标记外,还需要实现焦点,最后一条新增的属性值需要实现焦点定位。
在toLook函数中设置为row.flag = false;在toEditk函数中设置为row.flag = true;
toLook函数中除了设置完flag后,用户输入,失去焦点或者按下enter键后,我们需要对用户输入的数据进行校验(不能为空,不能和已经存在的重复)相关逻辑。row也存在于数组中,我们需要把自己拿出去和其他的进行比较。this.attrInfo.attrValueList.some中if判断就是把自己和其他进行比较。
toEditk函数中除了需要设置完flag后,点击span的时候,切换为input变为编辑模式,点击span的时候,重绘重拍一个input它是需要耗费事件,因此我们不可能一点击span立马获取到input;我们使用$nextTick,当节点渲染完毕,会执行一次。
3.3-新增和修改属性
我们需要收集表单数据(我们首先需要删除我们自定义的flag字段,然后需要过滤掉属性值为空的),然后点击保存按钮,向服务器发送请求,实现属性和属性值的变更。当我们属性值列表为空的时候,保存按钮应该不可用。
3.4-点击删除属性值
当我们点击属性值列表的删除属性值的时候,弹出气泡框,当我们点击确定的时候,我们先从数组中将属性值删除,真正删除后台数据是点击下面的保存按钮,提交数据。
3.5-点击删除属性
当我们点击属性列表页面的删除按钮,我们需要删除对应的属性。目前没有看到接口文档,暂时先忽略。