bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」

bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」一、功能需求         根据后台所给的原始数据,将其重组成bootstrap-treeview列表树插件所需要的数据结构并渲染,再根据所勾选的节点数据,重组成后台所需要的数据结构进行请求。其中在

一、功能需求

        根据后台所给的原始数据,将其重组成bootstrap-treeview列表树插件所需要的数据结构并渲染,再根据所勾选的节点数据,重组成后台所需要的数据结构进行请求。其中在勾选节点时,如果勾选父节点,则子节点全部被勾选;如果取消勾选父节点时,则子节点全部取消勾选;如果勾选其中某个子节点,则其所对应的父节点也被勾选

二、难点分析

其中难点主要有以下三个:

1、将原始数据重组成列表树插件所需要的数据结构;

2、其中某个子节点被勾选时,其父节点也被勾选;

3、将所有被勾选的节点数据重组成后台所需要的数据结构;

三、实例

关于bootstrap-treeview插件的依赖、使用方法、事件、可用事件列表可参考此处

1、插件依赖

本次实例使用的依赖如下:

  • bootstrap-3.4.1
  • jquery-3.1.1

bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」

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、效果展示

默认节点全选,如下图所示:

bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」

当父节点level1下有子节点被勾选时,父节点仍然被勾选,效果如图所示:

bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」点击“获取选中的节点”按钮,控制台输出最终重组后的数据,如图所示:

bootstrap+jquery+bootstrap-treeview实现菜单树极其父子节点的勾选功能「终于解决」

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

(0)

相关推荐

  • 算法小专栏:递归与尾递归[通俗易懂]

    算法小专栏:递归与尾递归[通俗易懂]本篇将介绍递归与尾递归的相关内容。 递归是一种优雅的解决问题的方法。 递归,简单来说,就是在运行的过程中调用自己。 递归能帮我们处理一些复杂的算法问题,但绝不能滥用递归。 在程序设计角度,循环的性能要好于递归。 从开发角度,使用递归,逻辑上更容易被理解。 所以,要分场合使用递归…

    2023-08-19
    129
  • 【2019年8月版】OCP 071认证考试原题-第39题「建议收藏」

    【2019年8月版】OCP 071认证考试原题-第39题「建议收藏」Choose two Exanine the desatption of the BOOKS_TRANSACTIONS table Name Null? Type —————–…

    2022-12-27
    149
  • 安装tesseract

    安装tesseract鉴于不同操作系统的差异,tesseract的安装方法也有所不同,但总体来说,tesseract的安装可以概括为以下几个步骤:

    2024-08-12
    24
  • JavaScript中向数组指定位置添加元素

    JavaScript中向数组指定位置添加元素对于开发者来说,在JavaScript中向数组指定位置添加元素是很常见的操作。实现这个功能,可以使用JavaScript内置的splice()方法完成。该方法可以接收3个参数:index(指定位置的下标)、howMany(需要删除的元素个数)和element1、element2、……、elementN(需要添加的元素)。因此,本文将详细阐述在JavaScript中实现向数组指定位置添加元素的方法,以及如何正确地使用splice()方法。

    2024-04-18
    70
  • 快递单打印软件(免费快递打单软件)

    快递单打印软件(免费快递打单软件)

    2023-09-14
    237
  • mysql 设置用户密码过期策略是什么_设置强制修改密码策略

    mysql 设置用户密码过期策略是什么_设置强制修改密码策略#全局设定mysql>SETGLOBALdefault_password_lifetime=90;单个用户设定为每个具体的用户账户单独设置特定的值ALTERUSER‘test’@‘localhost…

    2023-03-26
    154
  • Python isalpha函数:判断一个字符串是否全为字母

    Python isalpha函数:判断一个字符串是否全为字母Python中的isalpha函数是用来判断字符串是否只由字母组成的函数,如果字符串中全部由字母构成,返回True,否则返回False。它的语法如下:

    2024-04-10
    65
  • Python字符串的分割方法:split()

    Python字符串的分割方法:split()在Python中,字符串是一个非常常用的数据类型。在处理字符串时,有许多方法可以使用,其中最常用的莫过于split()方法。split()方法可以将一个字符串分割成多个子字符串,返回一个包含子字符串的列表。split()方法还可以接收一个参数,用于指定分割字符,如果不指定,则默认以空格为分隔符。

    2023-12-04
    174

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注