treeview插件使用:根据子节点选中父节点

  鄙人公司没有专门的前端,所以项目开发中都是前后端一起抡。最近用bootstrap用的比较频繁,发现bootstrap除了框架本身的样式组件外,还提供了多种插件供开发者选择。本篇博文讲的就是bootstrap的一个树形插件bootstrap-treeview。

  最近项目权限模块中,需要将用户菜单做成可配置的。授权人员的授权操作是通过对树形菜单中的复选框进行勾选后保存来完成的,如下图所示:

  bootstrap-treeview本身对勾选/取消的支持是没问题,问题在于复选框的业务逻辑上:

    ① 如果 勾选了父级节点,怎么让子节点全部变为勾选状态?

    ② 如果只选择了某个子节点,怎么让该节点所有的父节点全部变为选中状态?

  博主开发的时候也是问了度娘,但很多网友的分享让自己这样前端薄弱的人看得头大,所以项目功能实现后,特意整理了自己的简洁实现,如博友有更好的方法,欢迎告知,共同进步。

  首先,请求服务器后台获取的节点数据,通过树形插件的事件触发机制,在点击复选框做选中/取消操作的时候,去执行全选的代码:

function modify(id) {
    BASE.ajax("permission/pers", {
        id: id
    }, function (data) {
        $("#demoTree").treeview({
            color: "#428bca",
            data: data,
            levels: 1, //显示时展开到几级
            showIcon: false,
            showCheckbox: true,
            onNodeChecked: function (event, node) {  //选中事件
                checkAllNodes("checkNode", node);
            },
            onNodeUnchecked: function (event, node) { //取消事件
                checkAllNodes("uncheckNode", node);
            }
        });
        $("#modal").modal("show");
    });
}

   然后,通过对选中的当前节点进行遍历,对遍历出的节点执行选中;如果子节点还有子节点,很简单,递归一下就能搞定:

function checkAllNodes(method, node) {
    var $tree = $('#modifyTree');
    $(node.nodes).each(function (a, b) {
        //判断子节点存在,就执行相应的选中/取消事件。
        //each回调函数中参量:a表示节点索引,b表示节点对象
        $tree.treeview(method, [b.nodeId, {
            silent: true
        }]);
        if (b.nodes) //递归调用
            checkAllNodes(method, b);
    });
}

  自此,点击父节点 选中/取消 所有子节点的功能就算ok了。基于同样的思想,要想实现选中某一子节点后同时选中所有的父节点,那么只需要在代码中继续添加:① 通过子节点判断父节点的存在;② 选中父节点;③ 递归判断。

于是,上面的函数代码中就可以这样添加:

function checkAllNodes(method, node) {
    var $tree = $('#modifyTree');
    if (node.parentId) {//如果父节点存在,选中/去除父节点
        getParentNode(method, node, $tree);
    }
    $(node.nodes).each(function (a, b) {
        $tree.treeview(method, [b.nodeId, {
            silent: true
        }]);
        if (b.nodes)
            checkAllNodes(method, b);
    });
}

function getParentNode(method, node, tree) {
    tree.treeview(method, [node.parentId, {
        silent: true
    }]);
    var pnode = tree.treeview('getNode', node.parentId);
    if (pnode.parentId) //递归判断父节点是否还有父节点
        getParentNode(method, pnode, tree);
}

  自此,上面提到的两个问题就算是大功告成了。。。吗?稍等,如果这就算完成了,这篇博文记录对我实在没有多大意义。正当我喜滋滋的以为功能实现了的时候,突然发现了很大的bug,就是在通过子节点选中所有父节点的功能实现中,选中是没有问题,可是当取消某个子节点,无论兄弟节点是否有选中,父节点都一并被取消掉了。这肯定是有问题的。所以,自己又对取消事件单独做了判断,判断取消的时候,是否还有兄弟节点是处于选中状态,如果有,那么父节点就不执行取消了。代码如下:

function getParentNode(method, node, tree) {
    if (method == "uncheckNode") { //如果是取消事件,当判断兄弟节点是否存在
        var arr = tree.treeview('getSiblings', node);//获取兄弟节点
        for (var i = 0; i < arr.length; i++) {
            var brotherNode = arr[i];
            if (brotherNode.state.checked) { //判断兄弟节点是否用选中状态
                return;
            }
        }
    }
    tree.treeview(method, [node.parentId, {
        silent: true
    }]);
    var pnode = tree.treeview('getNode', node.parentId);
    if (pnode.parentId)
        getParentNode(method, pnode, tree);
}

  行文至此,上面的两个问题算是完美解决了。代码中的事件、属性,都是插件官网有详细说明的,插件使用过程中肯定需要根据业务需要去查询使用详情,再融合进自己的代码中的,不可生搬硬套。分享完结,希望能帮到一些人。如有疑惑或者更好的建议,留言讨论,不胜感激。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏idba

Python模块之subprocess

一 简介 在使用Python 开发MySQL自动化相关的运维工具的时候,遇到一些有意思的问题,本文介绍Python的 subprocess 模块以及如何和My...

15410
来自专栏更流畅、简洁的软件开发方式

【自然框架】 页面里的父类——把共用的东东都交给父类,让子类专注于其他。

【类图】 ? 【命名空间】——————————————————【文件截图】 ? ? 可能您会问,不就是弄个父类吗,怎么又是这么复杂呢?这个嘛,听...

23680
来自专栏程序员的知识天地

JavaWeb学习——4.XML

要写xml,第一步必须要有一个文档声明(写了文档声明之后,表示写xml文件的内容)

13420
来自专栏守望轩

Visual Studio 2008 每日提示(二十三)

#221、在对象浏览器中按对象和成员排序 原文链接:You can sort objects and members in the Object Browse...

38960
来自专栏前端下午茶

Vue项目数据动态过滤实践

这个问题是在下在做一个Vue项目中遇到的实际场景,这里记录一下我遇到问题之后的思考和最后怎么解决的(老年程序员记性不好 -。-),过程中会涉及到一些Vue源码的...

37240
来自专栏大前端_Web

javascript运行机制:并发模型 与Event Loop

版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

26910
来自专栏社区的朋友们

Java 动态加载 so 的解决方案

业务场景有对 so 实现动态加载/替换的需求,但 Java 并没有直接动态加载 so 的机制。本文将深度剖析 Java 加载 so 的实现机制,并提出一套 Ja...

1.9K10
来自专栏jouypub

优化Vue项目的文件大小

在使用Vue搭建项目时,经常由于引入的库太多,导致打包后的文件体积非常大,特别是vendor.js。这就造成页面第一次打开很慢,如果在浏览器中调试页面(打开控制...

34930
来自专栏老马寒门IT

07Vue.js快速入门-Vue路由详解

对于前端来说,其实浏览器配合超级连接就很好的实现了路由功能。但是对于单页面应用来说,浏览器和超级连接的跳转方式已经不能适用, 所以各大框架纷纷给出了单页面应用...

39450
来自专栏王磊的博客

富编译器汇总及二次开发Demo

富文本编译器汇总 名称 总大小 当前版本 官方地址 扩展方法 xhEditor 1.43 MB v1.1.14 http://xheditor.com...

33850

扫码关注云+社区

领取腾讯云代金券