大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」,希望您对编程的造诣更进一步.
一、功能需求
根据后台所给的原始数据,将其重组成bootstrap-treeview列表树插件所需要的数据结构并渲染,再根据所勾选的节点数据,重组成后台所需要的数据结构进行请求。其中在勾选节点时,如果勾选父节点,则子节点全部被勾选;如果取消勾选父节点时,则子节点全部取消勾选;如果勾选其中某个子节点,则其所对应的父节点也被勾选。
二、难点分析
其中难点主要有以下三个:
1、将原始数据重组成列表树插件所需要的数据结构;
2、其中某个子节点被勾选时,其父节点也被勾选;
3、将所有被勾选的节点数据重组成后台所需要的数据结构;
三、实例
关于bootstrap-treeview插件的依赖、使用方法、事件、可用事件列表可参考此处。
1、插件依赖
本次实例使用的依赖如下:
- bootstrap-3.4.1
- jquery-3.1.1
2、原始数据重组为插件所需数据结构
原始数据:
// 原始数据
var allLevels = {
"level1": ['level1-1', 'level1-2', 'level1-3', 'level1-4', 'level1-5'],
"level2": ['level2-1', 'level2-2', 'level2-3', 'level2-4', 'level2-5'],
"level3": ['level3-1', 'level3-2', 'level3-3', 'level3-4', 'level3-5'],
"level4": ['level4-1', 'level4-2', 'level4-3', 'level4-4', 'level4-5'],
"level5": ['level5-1', 'level5-2', 'level5-3', 'level5-4', 'level5-5'],
"level6": ['level6-1', 'level6-2', 'level6-3', 'level6-4', 'level6-5'],
"level7": ['level7-1', 'level7-2', 'level7-3', 'level7-4', 'level7-5'],
"level8": ['level8-1', 'level8-2', 'level8-3', 'level8-4', 'level8-5']
};
// 重组过后,可在treeview上渲染的数据
var treeData = [];
重组方法:
// 原始数据重组
function formatLevels(allLevels) {
// console.log(allLevels)
treeData = []// 清除菜单树缓存
treeData.push({
id: 'all',
text: '全选',
nodes: []
})
var level_number = -1
for (var level in allLevels) {
treeData[0].nodes.push({
id: level,
text: level,
nodes: []
})
level_number++
for (var index in allLevels[level]) {
treeData[0].nodes[level_number].nodes.push({
id: allLevels[level][index],
text: allLevels[level][index]
})
}
}
// console.log(treeData)//插件渲染数据
}
3、列表树渲染
HTML:
<div id="tree" style="height: 600px;overflow-y: auto;"></div>
js:
// treeview初始化
function initTreeView(treeData) {
$('#tree').treeview({
data: treeData,//赋值
showIcon: true,
showCheckbox: true,//展示checkbox
multiSelect: true,//是否可以同时选择多个节点
levels: 2,//设置继承树默认展开的级别。
onNodeChecked: function (event, node) { //选中节点时触发
var selectNodes = getChildNodeIdArr(node); //获取所有子节点
if (selectNodes) { //子节点不为空,则选中所有子节点
$('#tree').treeview('checkNode', [selectNodes, { silent: true }]);
}
// 以下代码实现当某个子节点被选中时,其父节点被选中
if (node.parentId >= 0) {//父节点不为空,则选中父节点
$("#tree").treeview("checkNode", [node.parentId, { silent: true }]);
var parentNode = $("#tree").treeview("getNode", node.parentId);
if (parentNode.parentId >= 0) {//1级父节点不为空,则选中父节点
$("#tree").treeview("checkNode", [parentNode.parentId, { silent: true }]);
var parentNode1 = $("#tree").treeview("getNode", parentNode.parentId);
if (parentNode1.parentId >= 0) {//2级父节点不为空,则选中父节点
$("#tree").treeview("checkNode", [parentNode1.parentId, { silent: true }]);
var parentNode2 = $("#tree").treeview("getNode", parentNode1.parentId);
}
}
}
setParentNodeCheck(node);
},
onNodeUnchecked: function (event, node) { //取消选中节点
var selectNodes = getChildNodeIdArr(node); //获取所有子节点
if (selectNodes) { //子节点不为空,则取消选中所有子节点
$('#tree').treeview('uncheckNode', [selectNodes, { silent: true }]);
}
},
}).treeview('checkAll', { silent: true });//默认全选
}
// 选中
function getChildNodeIdArr(node) {
var ts = [];
if (node.nodes) {
for (x in node.nodes) {
ts.push(node.nodes[x].nodeId);
if (node.nodes[x].nodes) {
var getNodeDieDai = getChildNodeIdArr(node.nodes[x]);
for (j in getNodeDieDai) {
ts.push(getNodeDieDai[j]);
}
}
}
} else {
ts.push(node.nodeId);
}
return ts;
}
// 取消选中
function setParentNodeCheck(node) {
var parentNode = $("#tree").treeview("getNode", node.parentId);
if (parentNode.nodes) {
var checkedCount = 0;
for (x in parentNode.nodes) {
if (parentNode.nodes[x].state.checked) {
checkedCount++;
} else {
break;
}
}
if (checkedCount === parentNode.nodes.length) {
$("#tree").treeview("checkNode", parentNode.nodeId);
setParentNodeCheck(parentNode);
}
}
}
4、根据所选节点数据,重组成后端所需数据结构
function initClick() {
// 点击按钮,获取被选中的节点,并组合成原始数据格式
$('.selectedNodes').on('click', function () {
var selectedNodes = $('#tree').treeview('getChecked');//获取被勾选的节点
// console.log(selectedNodes)
var parent_levels = {}//接收父节点
var son_levels = {}//接收子节点
var result_levels = {}//最终组合的数据
for (const item in selectedNodes) {
var name = selectedNodes[item].text
var nodeId = selectedNodes[item].nodeId
var parentId = selectedNodes[item].parentId
if (selectedNodes[item].parentId === undefined) {//去掉全选节点
continue
} else if (selectedNodes[item].parentId === 0) {//获取父节点key-value
parent_levels[name] = nodeId
} else {//获取子节点key-value
son_levels[name] = parentId
}
}
// console.log(parent_levels, son_levels)
for (const key in parent_levels) {
result_levels[key] = []
for (const index in son_levels) {
if (parent_levels[key] === son_levels[index]) {
result_levels[key].push(index)
}
}
}
// console.log(result_levels)
})
}
5、效果展示
默认节点全选,如下图所示:
当父节点level1下有子节点被勾选时,父节点仍然被勾选,效果如图所示:
点击“获取选中的节点”按钮,控制台输出最终重组后的数据,如图所示:
6、完整代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="./assest/bootstrap-3.4.1/css/bootstrap.css">
<style> .treeMenu { width: 600px; border: 1px solid #eee; margin: 20px auto; } </style>
</head>
<body>
<div class="treeMenu">
<div id="tree" style="height: 600px;overflow-y: auto;"></div>
<button class="selectedNodes">获取选中的节点</button>
</div>
</body>
</html>
<script type="text/javascript" src="./assest/jquery-3.1.1.min.js">
</script><script type="text/javascript" src="./assest/bootstrap-treeview/bootstrap-treeview.js">
</script><script type="text/javascript"> // 原始数据 var allLevels = { "level1": ['level1-1', 'level1-2', 'level1-3', 'level1-4', 'level1-5'], "level2": ['level2-1', 'level2-2', 'level2-3', 'level2-4', 'level2-5'], "level3": ['level3-1', 'level3-2', 'level3-3', 'level3-4', 'level3-5'], "level4": ['level4-1', 'level4-2', 'level4-3', 'level4-4', 'level4-5'], "level5": ['level5-1', 'level5-2', 'level5-3', 'level5-4', 'level5-5'], "level6": ['level6-1', 'level6-2', 'level6-3', 'level6-4', 'level6-5'], "level7": ['level7-1', 'level7-2', 'level7-3', 'level7-4', 'level7-5'], "level8": ['level8-1', 'level8-2', 'level8-3', 'level8-4', 'level8-5'] }; // 重组过后,可在treeview上渲染的数据 var treeData = []; $(document).ready(function () { // 将原始数据重组为treeview所要求的的格式 formatLevels(allLevels) // 初始化菜单树 initTreeView(treeData) // 点击事件初始化 initClick() }) // 原始数据重组 function formatLevels(allLevels) { // console.log(allLevels) treeData = []// 清除菜单树缓存 treeData.push({ id: 'all', text: '全选', nodes: [] }) var level_number = -1 for (var level in allLevels) { treeData[0].nodes.push({ id: level, text: level, nodes: [] }) level_number++ for (var index in allLevels[level]) { treeData[0].nodes[level_number].nodes.push({ id: allLevels[level][index], text: allLevels[level][index] }) } } // console.log(treeData) } // treeview初始化 function initTreeView(treeData) { $('#tree').treeview({ data: treeData,//赋值 showIcon: true, showCheckbox: true,//展示checkbox multiSelect: true,//是否可以同时选择多个节点 levels: 2,//设置继承树默认展开的级别。 onNodeChecked: function (event, node) { //选中节点时触发 var selectNodes = getChildNodeIdArr(node); //获取所有子节点 if (selectNodes) { //子节点不为空,则选中所有子节点 $('#tree').treeview('checkNode', [selectNodes, { silent: true }]); } // 以下代码实现当某个子节点被选中时,其父节点被选中 if (node.parentId >= 0) {//父节点不为空,则选中父节点 $("#tree").treeview("checkNode", [node.parentId, { silent: true }]); var parentNode = $("#tree").treeview("getNode", node.parentId); if (parentNode.parentId >= 0) {//1级父节点不为空,则选中父节点 $("#tree").treeview("checkNode", [parentNode.parentId, { silent: true }]); var parentNode1 = $("#tree").treeview("getNode", parentNode.parentId); if (parentNode1.parentId >= 0) {//2级父节点不为空,则选中父节点 $("#tree").treeview("checkNode", [parentNode1.parentId, { silent: true }]); var parentNode2 = $("#tree").treeview("getNode", parentNode1.parentId); } } } setParentNodeCheck(node); }, onNodeUnchecked: function (event, node) { //取消选中节点 var selectNodes = getChildNodeIdArr(node); //获取所有子节点 if (selectNodes) { //子节点不为空,则取消选中所有子节点 $('#tree').treeview('uncheckNode', [selectNodes, { silent: true }]); } }, }).treeview('checkAll', { silent: true });//默认全选 } // 选中 function getChildNodeIdArr(node) { var ts = []; if (node.nodes) { for (x in node.nodes) { ts.push(node.nodes[x].nodeId); if (node.nodes[x].nodes) { var getNodeDieDai = getChildNodeIdArr(node.nodes[x]); for (j in getNodeDieDai) { ts.push(getNodeDieDai[j]); } } } } else { ts.push(node.nodeId); } return ts; } // 取消选中 function setParentNodeCheck(node) { var parentNode = $("#tree").treeview("getNode", node.parentId); if (parentNode.nodes) { var checkedCount = 0; for (x in parentNode.nodes) { if (parentNode.nodes[x].state.checked) { checkedCount++; } else { break; } } if (checkedCount === parentNode.nodes.length) { $("#tree").treeview("checkNode", parentNode.nodeId); setParentNodeCheck(parentNode); } } } function initClick() { // 点击按钮,获取被选中的节点,并组合成原始数据格式 $('.selectedNodes').on('click', function () { var selectedNodes = $('#tree').treeview('getChecked');//获取被勾选的节点 // console.log(selectedNodes) var parent_levels = {}//接收父节点 var son_levels = {}//接收子节点 var result_levels = {}//最终组合的数据 for (const item in selectedNodes) { var name = selectedNodes[item].text var nodeId = selectedNodes[item].nodeId var parentId = selectedNodes[item].parentId if (selectedNodes[item].parentId === undefined) {//去掉全选节点 continue } else if (selectedNodes[item].parentId === 0) {//获取父节点key-value parent_levels[name] = nodeId } else {//获取子节点key-value son_levels[name] = parentId } } // console.log(parent_levels, son_levels) for (const key in parent_levels) { result_levels[key] = [] for (const index in son_levels) { if (parent_levels[key] === son_levels[index]) { result_levels[key].push(index) } } } console.log(result_levels) }) } </script>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13682.html