前端js动态解析复杂的dom结构
一、【 创作背景】
前端时间接到公司的一个需求,说是后端接口返回的数据存在较大的差异,其中json格式会给出来,但是对应的json格式会存在多种方式,如下所示:
二、【先睹为快】
json中包括文字块级展示,其中块级元素包括父子级别的关系,且要求在页面上通过背景色做区分,并且除了块级元素,还有表格元素,针对不同的json数据对应的元素还要添加其样式、点击事件等。废话不多说,先看json格式,然后再看json格式生成的页面结构:
json格式如下:
var arr = [
{
"block_name": "黄大大第一季",
"block_color": "red",
"block_type": "single",
"block_children": [{
"name": "第一集-啊啊",
"color": "blue",
"children": [
{
"name": "1-1",
"color": "rebeccapurple",
"click": {
"methods": "OBtargetInfoDetail('黄大大第一季 : 第一集-啊啊 1-1章节')"
}
}, {
"name": "1-2",
"color": "rebeccapurple"
}
],
"click": {
"methods": "OBtargetInfoDetail('黄大大第一季 : 第一集-啊啊')"
}
}, {
"name": "第二集-哈哈",
"color": "blue",
"children": [
{
"name": "2-1",
"color": "rebeccapurple"
}
]
}, {
"name": "第三集-更新中",
"color": "blue",
}]
}, {
"block_name": "黄大大第二季",
"block_color": "red",
"block_type": "multi",
"block_children": [{
"name": "第一集-吃吃",
"color": "blue",
}, {
"name": "第二集-喝喝",
"color": "blue",
}, {
"name": "第三集-吹吹",
"color": "blue",
"children": [
{
"name": "3-1",
"color": "rebeccapurple"
},
{
"name": "3-2",
"color": "rebeccapurple",
"children": [
{
"name": "3-2-1",
"color": "orange",
"click": {
"methods": "OBtargetInfoDetail('黄大大第二季 : 第三集-吹吹 3-2 3-2-1')"
}
},
{
"name": "3-2-2",
"color": "orange",
}
]
}
]
}]
},
{
"block_name": "OCEANBASE单层名称",
"block_type": "table", // 层类型:single(单层简单结构) / multi(多层嵌套结构) / table(表格结构)
"block_children": { // 表格展示
"head": ["租户ID", "名称", "CPU", "内存", "IO", "会话", "活跃会话", "诊断"],
"lines": [
[{ "val": "123", "color": "red" },
{ "val": "名称1" },
{ "val": "80%" },
{ "val": "80%", "color": "green" },
{ "val": "" },
{ "val": "" },
{ "val": "" },
{ "val": "诊断", "click": { "methods": "OBtargetInfoDetail('210100001')" } }],
[{ "val": "123" },
{ "val": "名称2", "color": "red" },
{ "val": "80%" },
{ "val": "80%", "color": "green" },
{ "val": "" },
{ "val": "" },
{ "val": "" },
{ "val": "诊断", "click": { "methods": "OBtargetInfoDetail('210100001')" } }],
]
}
}
]
通过前端代码解析生成的页面如下:
三、【实现剖析】
不难看出已经解析到第四层级的深度了,下面我将侧重讲述一下如何做到的
解决这个办法的核心在于递归调用页面解析的方法;
递归时候我们切记从最底层的地方着手,然后再不断的往上冒泡,将生成的页面结构字符串进行拼接,然后再渲染到页面即可;
其中递归的核心代码如下:
//加載多级联动
function loadDistriDom(domchild, loadHtmlStr) {
debugger;
if (domchild != null && domchild.length > 0) {
domNum++;
for (var k = 0; k < domchild.length; k++) {
onclickStr = "doNothing()";
if (domchild[k].click != null && domchild[k].click != undefined
&& domchild[k].click.methods != null && domchild[k].click.methods != undefined) {
onclickStr = domchild[k].click.methods;
}
if (domchild[k].children != null) {
loadHtmlStr += `<div class='blc_child` + domNum + `' οnclick="` + onclickStr + `">
<div style='color:`+ domchild[k].color + `'>` + domchild[k].name + `</div>
`+ loadDistriDom(domchild[k].children, "") + `
</div>`;
domNum--;
} else {
loadHtmlStr += `<div class='blc_child` + domNum + `' οnclick="` + onclickStr + `" style='color:` + domchild[k].color + `'>` + domchild[k].name + `</div>`
}
}
}
return loadHtmlStr;
}
在上面的逻辑中,主要判断是否还有孩子节点,如果有则递归调用,调用的过程中记得将原先的渲染页面字符串重新置空。另外值得注意的是domNum这个值得设置和修改过程,有孩子节点的切记形成dom后再执行–的操作,这个做的主要目的就是让页面的class名形成一个树状结构,如下所示:
调用方法如下:
for (var j = 0; j < arr.length; j++) {
loadHtmlStr = ``;
domNum = 0;
if (arr[j].block_type == "single" || arr[j].block_type == "multi") {
allStr += `<div class='bkchild bkchild_` + arr[j].block_type + `'>
<div style='color:`+ arr[j].block_color + `'>` + arr[j].block_name + `</div>
`+ loadDistriDom(arr[j].block_children, loadHtmlStr) + `
</div>`;
} else {
allStr += `<div class='bkchild bkchild_` + arr[j].block_type + `'>
<div style='color:`+ arr[j].block_color + `'>` + arr[j].block_name + `</div>
` + loadDistriTable(arr[j].block_children) + `</div>`
}
}
通过上面的一系列操作和递归调用,不过json数据的层级有多深,我们都是可以来实现页面的层级模块的展示,这个还可以广泛应用于多级菜单的形成。
四、源码完整包分享
百度网盘
链接:https://pan.baidu.com/s/158YrxeOj9SuNx83_gH9NjQ
提取码:hdd6
123云盘(不限速)
https://www.123pan.com/s/ZxkUVv-1EJ4
提取码:hdd6
有什么不懂的可以留言,动动发财的小手,点个赞关注下,支持博主创作的可以上皇榜哟,皇榜点击此处;
知识的道路上,愿与君同行!