需求背景:
项目web端系统中有一处功能,需要通过http post请求后端提供的API接口,传入登录用户所属部门id参数,动态获取未知级数的级联部门数据的,再进行前端解析,构造成能装入el-cascader级联选择框组件中的数据结构?
继上文: mysql分级无限下钻递归查询sql
已实现无限级联部门数据的查询sql,可以编写通过用户所属部门id查询动态级联部门数据的API。
1. 后端API返回的数据结构
前端通过http请求该接口,返回的数据结构如下:
const data = [
{
"id": 1,
"name": "司令",
"parentId": 0
},
{
"id": 2,
"name": "军长",
"parentId": 1
},
{
"id": 3,
"name": "师长A",
"parentId": 2
},
{
"id": 4,
"name": "师长A",
"parentId": 2
},
{
"id": 5,
"name": "旅长",
"parentId": 3
},
{
"id": 6,
"name": "团长",
"parentId": 5
},
{
"id": 7,
"name": "营长A",
"parentId": 6
},
{
"id": 8,
"name": "营长B",
"parentId": 6
},
{
"id": 9,
"name": "连长A",
"parentId": 7
},
{
"id": 10,
"name": "连长B",
"parentId": 8
},
{
"id": 11,
"name": "连长C",
"parentId": 8
},
{
"id": 12,
"name": "排长A",
"parentId": 9
},
{
"id": 13,
"name": "排长B",
"parentId": 11
}
]
2. 前端解析构造el-cascader组件适配的数据结构
返回的数据属于一维数组结构,但是此结构的数据无法直接填入ElementUI的Cascader级联选择器组件中,因此需要在前端实现数据的重新构造,构造方法如下:
// 构造任意级数的部门级联数据
const transformTree = function(list, userDepartmentId){
let newArr=[]
list.filter(v=>v.id==userDepartmentId).forEach(d=>{
let item = queryChildren(d, list)
item.label = d.name
item.value = d.id
newArr.push(item)
})
return newArr;
}
// 递归构造子级(children)数据
const queryChildren = function(parent, list){
let new_parent = []
new_parent.label = parent.name
new_parent.value = parent.id
let children = []
list.filter(v=>v.parentId == parent.id).forEach(v=>{
let item1 = queryChildren(v, list)
item1.label = v.name
item1.value = v.id
children.push(item1)
})
if(children.length){
new_parent.children = children;
}
return new_parent;
}
let userDepartmentId = 5
// data是请求返回的部门数据
// userDepartmentId是登录用户所属部门id(因为不同的登录用户看到的级联组件中的数据是不一样的,无法看到或操作其父级部门的数据)
let new_data = transformTree(data, userDepartmentId)
console.log(new_data);
构造后的数据结构如下:
如果有多个层级的子级,则以嵌套children数组的形式呈现。
3. 页面效果呈现
将解析后的数据直接绑定到el-cascader组件中,这里已传入userDepartmentId = 5为例:
4. 完整样例代码
可以将代码拷贝到 ElementUI提供的在线运行平台上测试效果:https://codepen.io/pen
HTML
<script src="//unpkg.com/vue@2/dist/vue.js"></script>
<script src="//unpkg.com/element-ui@2.15.10/lib/index.js"></script>
<div id="app">
<div class="block">
<span class="demonstration">单选可搜索</span>
<el-cascader
placeholder="试试搜索:指南"
:options="options"
filterable></el-cascader>
</div>
</div>
CSS
@import url("//unpkg.com/element-ui@2.15.10/lib/theme-chalk/index.css");
JS
var Main = {
data() {
return {
options: []
};
},
mounted(){
const data = [
{
"id": 1,
"name": "司令",
"parentId": 0
},
{
"id": 2,
"name": "军长",
"parentId": 1
},
{
"id": 3,
"name": "师长A",
"parentId": 2
},
{
"id": 4,
"name": "师长A",
"parentId": 2
},
{
"id": 5,
"name": "旅长",
"parentId": 3
},
{
"id": 6,
"name": "团长",
"parentId": 5
},
{
"id": 7,
"name": "营长A",
"parentId": 6
},
{
"id": 8,
"name": "营长B",
"parentId": 6
},
{
"id": 9,
"name": "连长A",
"parentId": 7
},
{
"id": 10,
"name": "连长B",
"parentId": 8
},
{
"id": 11,
"name": "连长C",
"parentId": 8
},
{
"id": 12,
"name": "排长A",
"parentId": 9
},
{
"id": 13,
"name": "排长B",
"parentId": 11
}
];
this.options = this.transformTree(data, 5)
console.log(this.options)
},
methods:{
// 构造任意级数的部门级联数据
transformTree:function(list, userDepartmentId){
let newArr=[]
list.filter(v=>v.id==userDepartmentId).forEach(d=>{
let item = this.queryChildren(d, list)
item.label = d.name
item.value = d.id
newArr.push(item)
})
return newArr;
},
// 递归构造子级(children)数据
queryChildren:function(parent, list){
let new_parent = []
new_parent.label = parent.name
new_parent.value = parent.id
let children = []
list.filter(v=>v.parentId == parent.id).forEach(v=>{
let item1 = this.queryChildren(v, list)
item1.label = v.name
item1.value = v.id
children.push(item1)
})
if(children.length){
new_parent.children = children;
}
return new_parent;
}
}
};
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
5. 级联下拉框选择后的数据获取
注意:级联下拉框组件在选择后,获取数据需要注意
// 如果departmentId1的值是通过部门级联下拉菜单选出的(数组)对象,则取(数组)对象最后一个元素作为departmentId1的值
if (departmentId1 instanceof Object) {
let departmentIdArr = Array.prototype.slice.call(departmentId1);
// 收起下拉菜单
if (departmentIdArr.length > 0) {
this.$refs.cascader1.dropDownVisible = false;
}
departmentId1 = departmentIdArr[departmentIdArr.length - 1];
}
6. 参考链接
Js 如何把数据变成级联结构数据 - 作者:甘道夫老矣