Jquery 实现树

122 阅读1分钟

产品需求,10W条数据渲染一个树形组件,使用市场插件,会样式丢失,无奈只能自己写一个。感觉不是在造树,而是在造森林!吐槽产品经理

  • 问题:
    • 数据过多样式丢失
    • 递归过多,Jquery会报错 报错
  • 解决办法
    • 使用行内样式
    • 点击节点时请求加载数据,渲染子节点

效果预览

<html>
<head>
</head>
<body>
    <div>
        <div><button onclick="getCheckedNodes()">查看选中</button></div>
        <hr />
        <ul id="treeDiv" style="list-style: none;">

        </ul>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
    <script>
        let treeDataInfos = [{
                id: 1,
                title: 'AAA',
                children: [{
                        id: 12,
                        title: 'AAA',
                        parentIds: "1",
                    },
                    {
                        id: 13,
                        title: 'AAA',
                        parentIds: "1",
                    },
                    {
                        id: 14,
                        title: 'AAA',
                        parentIds: "1",
                    },
                    {
                        id: 15,
                        title: 'AAA',
                        parentIds: "1",
                    }
                ]
            },
            {
                id: 2,
                title: 'AAA'
            },
            {
                id: 3,
                title: 'AAA',
                children: [{
                        id: 31,
                        title: 'AAA',
                        parentIds: "3",
                    },
                    {
                        id: 32,
                        title: 'AAA',
                        parentIds: "3",
                    },
                    {
                        id: 33,
                        title: 'AAA',
                        parentIds: "3",
                    },
                    {
                        id: 34,
                        title: 'AAA',
                        parentIds: "3",
                        children: [{
                                id: 341,
                                title: 'AAA',
                                parentIds: "3,34",
                            },
                            {
                                id: 342,
                                title: 'AAA',
                                parentIds: "3,34",
                            },
                            {
                                id: 343,
                                title: 'AAA',
                                parentIds: "3,34",
                            },
                            {
                                id: 344,
                                title: 'AAA',
                                parentIds: "3,34",
                            }
                        ]
                    }
                ]
            },
        ]

        //默认是否展开树节点
        let childNodeToggle = 'show'; //show|none
        $(document).ready(function () {
            // initTree();
            let treeHtmlContent = createTreeNode(treeDataInfos);
            //渲染树
            $("#treeDiv").empty().html(treeHtmlContent.join(""));
            self.treeEvents();
        });

        function initTree() {
            let self = this;
            $.ajax({
                url: 'http://localhost:9090/tree',
                type: 'GET', // 默认为GET
                data: {

                },
                timeout: 50000, // 超时时间
                // beforeSend:function(xhr){
                //   console.log(xhr)
                //   console.log('发送前')
                // },
                success: function (result) {
                    let treeHtmlContent = createTreeNode(result);
                    //渲染树
                    $("#treeDiv").empty().html(treeHtmlContent.join(""));
                    self.treeEvents();
                },
                error: function (xhr, textStatus) {
                    console.log('错误')
                    console.log(xhr)
                    console.log(textStatus)
                }
            })

        }


        function treeEvents() {
            //节点收缩方法
            $(".parentNode").each(function () {
                $(this).click(function () {
                    let id = $(this).attr("node");
                    let ischildren = $(this).attr("ischildren");
                   
                    if (ischildren) {
                        $("#childrenNode" + id).fadeToggle(500);
                    }

                });
            });

            //复选框改变
            $(".parentNodeCheckbox").change(function () {
                let id = $(this).attr("node");
                let parentIds = $(this).attr("parentnodes");
                let checkedStatus = $(this)[0].checked;
                //如果有子节点全部变更状态
                $("#childrenNode" + id + " .parentNodeCheckbox").prop("checked", checkedStatus);
                //如果有父节点,变更父节点状态
                if (parentIds) {
                    //反向依次选中
                    let parentIdsArray = parentIds.split(",").reverse();
                    for (const parentId of parentIdsArray) {
                        //如果状态是选中,判断父节点下是否有有未选中的,若有则不处理,无则选中
                        if (checkedStatus) {
                            if (!getIsNotCheckedNode(parentId)) {
                                $("#parentNodeCheckbox" + parentId).prop("checked", true);
                            }
                        } else {
                            //依次变更父节点状态为未选中
                            $("#parentNodeCheckbox" + parentId).prop("checked", false);
                        }
                    }
                }
            });

        }

        //判断父节点下是否全部选中
        function getIsNotCheckedNode(id) {
            let isNotCheckedNode = false;
            let childrenNodes = $("#childrenNode" + id + " .parentNodeCheckbox");
            for (const childrenContent of childrenNodes) {
                if (!$(childrenContent)[0].checked) {
                    isNotCheckedNode = true;
                    break;
                }
            }
            return isNotCheckedNode;
        }

        //渲染树节点,递归思想
        function createTreeNode(contents) {
            let treeHtml = [];
            for (const content of contents) {
                treeHtml.push('<li style="list-style: none;">');
                let isChildren = false;
                if (content.children) {
                    isChildren = true;
                    treeHtml.push('<span style="width: 10px;font-size: x-large;color: #0488f1;">+</span>');
                } else {
                    treeHtml.push('<span style="width: 10px;font-size: x-large;color: #E91E63;">- </span>');
                }
                //复选框
                treeHtml.push('<input type="checkbox"   class="parentNodeCheckbox" node="' + content.id +
                    '" parentnodes="' + content.parentIds + '"  id="parentNodeCheckbox' + content.id + '"/>');
                //title
                treeHtml.push('<span class="parentNode" style="cursor:pointer;" ischildren="' + isChildren + '" node="' + content.id + '" >' +
                    content.title + '-' + content.id + '</span>');
                //子节点
                if (isChildren) {
                    treeHtml.push('<ul  class="childrenNode" node="' + content.id + '" id="childrenNode' + content.id +
                        '" style="list-style: none;display:' + childNodeToggle + '">');
                    treeHtml = treeHtml.concat(createTreeNode(content.children));
                    treeHtml.push('</ul>');
                }
                treeHtml.push('</li>');
            };
            return treeHtml;
        }

        //获取选中的节点
        function getCheckedNodes() {
            let checkedNodes = [];
            $(".parentNodeCheckbox").each(function () {
                let checkedStatus = $(this)[0].checked;
                if (checkedStatus) {
                    let id = $(this).attr("node");
                    checkedNodes.push(id);
                }
            })
            console.log(checkedNodes);
        }
    </script>
</body>

</html>