用el-tree组件配合插槽完成主体布局
<el-tree >
<el-tree
:data="list"
:default-expand-all="true"
>
<!-- 作用域插槽 data拿到的是每一个子节点的对象 -->
<!--
#default === slot-scope
什么时候用到作用域插槽?父组件中如果想使用子组件中的数据进行自定义内容的渲染 (类似于table 单元格数据渲染)
-->
<template #default="{ data }">
<el-row
type="flex"
justify="space-between"
align="middle"
style="height: 40px; width: 100%;"
>
<el-col :span="20">
<span>{
{ data.name }}</span>
</el-col>
<el-col :span="4">
<el-row type="flex" justify="end">
<!-- 两个内容 -->
<el-col>{
{ data.manager }}</el-col>
<el-col>
<!-- 下拉菜单 element -->
<el-dropdown>
<span> 操作<i class="el-icon-arrow-down" /> </span>
<!-- 下拉菜单 -->
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>添加子部门</el-dropdown-item>
<el-dropdown-item>编辑部门</el-dropdown-item>
<el-dropdown-item>删除部门</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-col>
</el-row>
</el-col>
</el-row>
</template>
</el-tree>
el-tree的基本使用
-
树形组件依赖一份结构为树形嵌套的数据结构
-
data 中默认
label
为节点标签的文字,children
为子节点 (可以通过 props 修改默认配置 )
<script>
export default {
data() {
return {
// 依赖一份树形数据
list: [{
name: '财务部',
manager: '刘备'
children: [
{
name: '财务核算部',
manager: '张飞'
},
{
name: '税务核算部',
manager: '关羽'
}
]
}]
}
}
}
</script>
扁平化数据处理树形结构
续新增弹层的实现完善
新增和编辑为一个弹窗
新增状态 处理新增和编辑弹窗状态
父组件的代码
补充数据项isEdit,来标识当前是否处于编辑状态
点击添加时,这个值是false
点击编辑时,这个值是true
把这个数据项传递给子组件
给编辑部门添加事件 弹窗获取id 传给子组件
在子组件中 根据id获取单个部门信息 实现数据回填
做数据回填时,由于form已经做了v-model双向绑定,所以,这里直接赋值:this.form = res.data
,这样数据就回填了。
图解
组织架构-编辑数据-保存更新
图解
在src\api\departments.js中,添加一个用于更新部门数据的接口
封装更新接口
调用接口,保存数据;
保存成功之后,通知父组件:关闭弹层,更新数据;
补充doEdit 操作
async为微任务
微任务 =>dom加载 => 宏任务
加$nextTick或setTimeout 将微任务转宏任务
表单重新加载 重新获取数据
方法一
在关闭弹层时,把子组件销毁
方法二 通过给组件添加ref $nextTick回调函数中调用请求时间
方法三
通过给id 添加事件监听 监听id变化
删除部门
优化删除
给取消按钮增加关闭弹层功能
表单校验
在父组件中
通过对数据的解构赋值操作 获得表单校验所需要的属性
定义空对象 originList接收
在子组件标签上通过 :origin-list="originList"传递给子组件
在子组件中 通过props接收 数组
验证校验规则 部门编码
通过map循环遍历获取所有的 部门编码 保存在existCodeList接收
通过includes 判断对象中的value是否存在 若存在callback(new Error('部门编码存在')) 若不存在callback()
完善修改状态下自身 编码 的校验问题
// 验证部门编码是否重复
const validCode = (rule, value, callback) => {
console.log(this.originList.map(item => item.code), '1111111111')
const existCodeList = this.originList.map(item => item.code)
console.log(existCodeList, 'existCodeList')
if (this.isEdit) {
// 所有的id 不等于当前id 排除自己的id 获取code将其余数据保存在新的数组
this.originList.filter(item => item.id !== this.id).map(item => item.code)
}
existCodeList.includes(value) ? callback(new Error('部门编码已存在')) : callback()
}
验证校验规则 部门名称
通过当前的id找到父级 找到所有的子级的name
item.pid==this.id获取到当前id所在的父级 通过map获取到所有子级元素的name
完善编辑状态下部门名称重复问题
如果是编辑状态
通过id找到当前的子的pid
通过当前子的pid找到当前父下所有的pid, 排除自己 后获取所有的 name
const validName = (rule, value, callback) => {
// 通过当前id 获取到父级 找到父级下面所有的name
let existNameList = this.originList.filter(item => item.pid === this.id).map(item => item.name)
if (this.isEdit) {
// 找到 当前id所在的子的 的pid
const pid = this.originList.find(item => item.id === this.id).pid
// 通过当前pid找到父级下的所有儿子 获得所有的兄弟 排除自己 再获取所有的name
existNameList = this.originList.filter(item => item.pid === pid).filter(item => item.id !== this.id).map(item => item.name)
}
existNameList.includes(value) ? callback(new Error('此部门已存在')) : callback()
console.log(existNameList)
}
点击确认 兜底校验
在子组件定义 重置表单函数
在父组件 的子标签中定义closed事件 hClose
在hClose中调用子组件的函数完成表单的重置
解决数据编辑时 残留问题
v-if="showDialog"
强制子组件发送请求 重新获取数据
方法三 :添加watch事件
监听id的变化
id变化后重新发送请求
将路由模块化处理
将department 和 employee路由模块化处理
在module里面新建两个js文件