美文网首页
树形结构菜单

树形结构菜单

作者: 小柠有点萌 | 来源:发表于2020-08-04 14:05 被阅读0次
    image.png

    不使用插件封装

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
        <title></title>
        <link rel="stylesheet" href="css/reset.min.css">
        <style>
            .container {
                box-sizing: border-box;
                margin: 20px auto;
                padding: 10px;
                width: 600px;
                height: 300px;
                border: 1px dashed #AAA;
                -webkit-user-select: none;
                overflow: auto;
            }
    
            .level {
                display: none;
                font-size: 14px;
                margin-left: 10px;
            }
    
            .level.level0 {
                display: block;
                margin-left: 0;
            }
    
            .level li {
                position: relative;
                padding-left: 15px;
                line-height: 30px;
            }
    
            .level li .icon {
                position: absolute;
                left: 0;
                top: 9px;
                box-sizing: border-box;
                width: 12px;
                height: 12px;
                line-height: 8px;
                text-align: center;
                border: 1px solid #AAA;
                background: #EEE;
                cursor: pointer;
            }
    
            .level li .icon:after {
                display: block;
                content: "+";
                font-size: 12px;
                font-style: normal;
            }
    
            .level li .icon.open:after {
                content: "-";
            }
    
            .level li .title {
                color: #000;
            }
        </style>
        </head>
        <body>
            <div class="container">
                <ul class="level level0" id="zTree1"></ul>
            </div>
    
        <script type="text/javascript">
            (async function(){
                function queryData() {
                    return new Promise(resolve => {
                        let xhr = new XMLHttpRequest;
                        xhr.open('GET', './data.json');
                        xhr.send();
                        xhr.onreadystatechange = function () {
                            if (xhr.status === 200 && xhr.readyState === 4) {
                                resolve(JSON.parse(xhr.responseText));
                            }
                        };
                        
                    });
                }
                let result=await queryData();
                let  i=0;
                function bindHtml(result){
                    i++;
                    let str = ``;
                    result.forEach(element => {
                        let {
                                name,
                                children,
                                open
                            } = element;
                            
                        str += `<li>
                            <a href="javascript:;" class="title">${name}</a>
                            ${children && children.length>0?`
                                <em class="icon ${open?'open':''}"></em>
                                <ul class="level level${i}" 
                                    style="display:${open?'block':'none'}">
                                    ${bindHtml(children)}
                                </ul>
                            `:``}
                        </li>`
                    });
                    i--;
                    return  str;
                }
                let zTree=document.querySelector("#zTree1");
                zTree.innerHTML=bindHtml(result);
    
                zTree.addEventListener('click', (ev) => {
                    // this -> 实例
                    let target = ev.target,
                        targetTag = target.tagName;
                    // 合并事件源(把A处理成为EM)
                    if (targetTag === 'A') {
                        target = target.nextElementSibling;
                        targetTag = target ? "EM" : "";
                    }
    
                    // 如果事件源是EM
                    if (targetTag === "EM") {
                        let ulBox = target.nextElementSibling;
                        if (!ulBox) return;
                        let sty = ulBox.style.display;
                        if (sty === "block") {
                            // 当前是展示的:我们让其隐藏
                            ulBox.style.display = "none";
                            target.className = "icon";
                            return;
                        }
                        // 当前是隐藏的:我们让其展示
                        ulBox.style.display = "block";
                        target.className = "icon open";
                        return;
                    }
                });
                })();
            </script>
    
    </body>
    </html>
    

    使用插件封装

    html

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8">
        <title>zTree树形结构菜单</title>
        <!-- import css -->
        <link rel="stylesheet" href="css/reset.min.css">
        <style>
            .container {
                box-sizing: border-box;
                margin: 20px auto;
                padding: 10px;
                width: 600px;
                height: 300px;
                border: 1px dashed #AAA;
                -webkit-user-select: none;
                overflow: auto;
            }
    
            .level {
                display: none;
                font-size: 14px;
                margin-left: 10px;
            }
    
            .level.level0 {
                display: block;
                margin-left: 0;
            }
    
            .level li {
                position: relative;
                padding-left: 15px;
                line-height: 30px;
            }
    
            .level li .icon {
                position: absolute;
                left: 0;
                top: 9px;
                box-sizing: border-box;
                width: 12px;
                height: 12px;
                line-height: 8px;
                text-align: center;
                border: 1px solid #AAA;
                background: #EEE;
                cursor: pointer;
            }
    
            .level li .icon:after {
                display: block;
                content: "+";
                font-size: 12px;
                font-style: normal;
            }
    
            .level li .icon.open:after {
                content: "-";
            }
    
            .level li .title {
                color: #000;
            }
        </style>
    </head>
    
    <body>
        <div class="container">
            <ul class="level level0" id="zTree1"></ul>
        </div>
    
        <div class="container">
            <ul class="level level0" id="zTree2"></ul>
        </div>
    
        <div class="container">
            <ul class="level level0" id="zTree3"></ul>
        </div>
    
        <!-- IMPORT JS -->
        <!-- 
            写插件(目的是重复利用):
            1. 先把一个的效果/功能实现全了
            2. 把插件的配置和功能需求规划好
            3. 基于面向对象实现插件化开发(面向对象中:每一个插件就是一个类,调用插件就是创建这个类的一个实例,这样既可以实现某些信息的私有化,也可以实现某些方法公用)
         -->
        <!-- <script src="js/zTree.js"></script> -->
        <script src="js/zTree-plugin.js"></script>
        <script>
            // $zTree([element],[data]);
            function queryData() {
                return new Promise(resolve => {
                    let xhr = new XMLHttpRequest;
                    xhr.open('GET', './data.json');
                    xhr.onreadystatechange = function () {
                        if (xhr.status === 200 && xhr.readyState === 4) {
                            resolve(JSON.parse(xhr.responseText));
                        }
                    };
                    xhr.send(null);
                });
            }
    
            queryData().then(result => {
                $zTree(zTree1, result);
                $zTree(zTree2, result);
                $zTree(zTree3, result);
            });
        </script>
    </body>
    
    </html>
    

    js/zTree-plugin.

    /* 
    let $zTree = (function () {
        function $zTree(element, data) {
            return new $zTree.fn.init(element, data);
        }
        $zTree.fn = $zTree.prototype = {
            constructor: $zTree,
            //...
        };
    
        let init = $zTree.fn.init = function init(element, data) {
    
        };
        init.prototype = $zTree.fn;
    
        return $zTree;
    })();
     */
    
    
    let $zTree = (function () {
        class zTree {
            // this.xxx=xxx 设置私有属性
            constructor(element, data) {
                // 把参数挂载到实例上,这样我们就可以在其它方法中基于this.xxx获取到这些信息了(一般我们把需要在其它方法中使用的信息都挂载到实例上:这样可以实现信息的公用,也是面向对象插件开发的优势 => 保证各个方法中的THIS是实例)
                this.element = element;
                this.data = data;
                this.level = 0;
                this.init();
            }
            // zTree.prototype
            bindHTML(result) {
                this.level++;
                let str = ``;
                result.forEach(item => {
                    let {
                        name,
                        children,
                        open
                    } = item;
                    str += `<li>
                        <a href="javascript:;" class="title">${name}</a>
                        ${children && children.length>0?`
                            <em class="icon ${open?'open':''}"></em>
                            <ul class="level level${this.level}" 
                                style="display:${open?'block':'none'}">
                                ${this.bindHTML(children)}
                            </ul>
                        `:``}
                    </li>`;
                });
                this.level--;
                return str;
            }
            delegate() {
                this.element.addEventListener('click', (ev) => {
                    // this -> 实例
                    let target = ev.target,
                        targetTag = target.tagName;
    
                    // 合并事件源(把A处理成为EM)
                    if (targetTag === 'A') {
                        target = target.nextElementSibling;
                        targetTag = target ? "EM" : "";
                    }
    
                    // 如果事件源是EM
                    if (targetTag === "EM") {
                        let ulBox = target.nextElementSibling;
                        if (!ulBox) return;
                        let sty = ulBox.style.display;
                        if (sty === "block") {
                            // 当前是展示的:我们让其隐藏
                            ulBox.style.display = "none";
                            target.className = "icon";
                            return;
                        }
                        // 当前是隐藏的:我们让其展示
                        ulBox.style.display = "block";
                        target.className = "icon open";
                        return;
                    }
                });
            }
            init() {
                // 在这里控制先做什么再做什么的逻辑顺序(大脑)
                // 1.数据绑定,this.element是DOM,this.data是数据
                this.element.innerHTML = this.bindHTML(this.data);
                // 2.事件委托实现效果
                this.delegate();
            }
        }
    
        return function $zTree(element, data) {
            // init params
            if (element == null || typeof element !== "object" || element.nodeType !== 1) {
                throw new TypeError('element must to be a html element!');
            }
            if (data == null || !Array.isArray(data) || data.length <= 0) {
                throw new TypeError('data must to be a array and not empty!');
            }
            return new zTree(element, data);
        };
    })();
    

    reset.min.css

    body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,button,input,textarea,th,td{margin:0;padding:0}body{font-size:12px;font-style:normal;font-family:"\5FAE\8F6F\96C5\9ED1",Helvetica,sans-serif}small{font-size:12px}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4,h5,h6{font-size:100%}ul,ol{list-style:none}a{text-decoration:none;background-color:transparent}a:hover,a:active{outline-width:0;text-decoration:none}table{border-collapse:collapse;border-spacing:0}hr{border:0;height:1px}img{border-style:none}img:not([src]){display:none}svg:not(:root){overflow:hidden}html{-webkit-touch-callout:none;-webkit-text-size-adjust:100%}input,textarea,button,a{-webkit-tap-highlight-color:rgba(0,0,0,0)}article,aside,details,figcaption,figure,footer,header,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block}audio:not([controls]),video:not([controls]){display:none;height:0}progress{vertical-align:baseline}mark{background-color:#ff0;color:#000}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}button,input,select,textarea{font-size:100%;outline:0}button,input{overflow:visible}button,select{text-transform:none}textarea{overflow:auto}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-input-placeholder{color:inherit;opacity:.54}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}.clearfix:after{display:block;height:0;content:"";clear:both}
    

    相关文章

      网友评论

          本文标题:树形结构菜单

          本文链接:https://www.haomeiwen.com/subject/xsslqktx.html