原生js实现折叠菜单组件开发

折叠菜单

功能需求:

  1. 根据数据内容创建折叠菜单内容,显示在页面中;
  2. 点击一级菜单,如果点击的一级菜单下有对应的子菜单,则让其展开;如果没有子菜单,则不能点击;
  3. 要考虑到三级菜单、四级菜单…的显示;

先来看一下效果:
折叠菜单
因为不确定一共有几级菜单,考虑到多级菜单出现的情况,可以使用递归回调函数;数据结构一定要统一,方便对数据进行操作。

下面附上代码

html代码,模拟菜单数据,实例化折叠菜单:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>foldMenu</title>
</head>

<body>
    <script type="module">
        import Menu from './js/Menu.js';
        var arr=[
            {name:"今日爆款",category:[
                {name:"热销商品",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"},{name:"店长推荐",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"}
            ]},
            {name:"新品上市",category:[
                {name:"施华洛世奇联名故宫宫廷文化",category:[
                    {name:"故宫文创",category:[
                        {name:"御猫",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"},{name:"紫禁城里过大年",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"}
                    ]},
                    {name:"故宫博物馆",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"}
                ]},{name:"12月新品",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"}
            ]},
            {name:"折扣专区",category:[]},
            {name:"专柜爆款",category:[
                {name:"时尚尖货",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"},{name:"专柜爆款",href:"https://blog.csdn.net/Charissa2017/article/details/103855079"}
            ]},
            {name:"品牌畅销系列",category:[
                {name:"BEE A QUEEN女王系列",href:""},
                {name:"蓝色天鹅专区",category:[
                    {name:"白天鹅",href:""},{name:"黑天鹅",href:""},{name:"蓝色天鹅",href:""}
                ]},{name:"MY HERO",href:""},{name:"LISABEL蜜蜂",href:""},
                {name:"Sparkling Dance",href:""},{name:"Remix系列",href:""},{name:"Magic唯美雪花",href:""},{name:"MICKEY&MINNIE系列",href:""}
            ]},
        ]
        init();
        function init(){
            let menu=new Menu(arr);
            menu.appendTo("body");
        }
    </script>
</body>
</html>

Menu.js文件,用来实现对数据的操作处理,创建菜单:

import Utils from './Utils.js';
export default class Menu{
    constructor(_list){
        this.elem=this.createElem(_list);
    }
    createElem(_list){
        if(this.elem) return this.elem;
        //创建最外层ul容器
        let ul=Utils.createE("ul",{
            listStyle:"none",
            padding:"0px",
            margin:"0px",
            width:"235px",
            border:"1px solid #f5f5f5",
            color:"#333",
            fontSize:"14px",
            userSelect: "none"
        });
        //创建li列表
        this.createMenu(_list,ul);
        //ul监听点击事件
        ul.addEventListener("click",e=>this.clickHandler(e));
        return ul;
    }
    appendTo(parent){
        Utils.appendTo(this.elem,parent);
    }
    //创建一级菜单
    createMenu(_list,parent){
        for(let i=0;i<_list.length;i++){
            let li=Utils.createE("li",{
                background:"#f5f5f5",
                borderBottom:"1px solid #ddd",
                lineHeight:"30px",
                cursor:"pointer"
            },{
                textContent:_list[i].name
            })
            let span=Utils.createE("span",{
                display:"inline-block",
                width:"16px",
                height:"16px",
                background:"#ddd",
                lineHeight:"12px",
                textAlign:"center",
                float:"left",
                margin:"7px 15px 0px 8px"
            },{
                textContent:_list[i].category.length>0? "+" : "-"
            })
            Utils.appendTo(span,li);
            Utils.appendTo(li,parent);
            //创建子菜单
            this.createSubMenu(_list[i].category,li);
        }
    }
    //创建子菜单
    createSubMenu(_subList,parent){
        //如果当前菜单没有子菜单,则跳出
        if(_subList.length===0) return;
        let subUl=Utils.createE("ul",{
            listStyle:"none",
            background:"#fff",
            padding:"0px",
            margin:"0px",
            fontSize:"14px",
            display:"none"
        })
        for(let i=0;i<_subList.length;i++){
            let subLi=Utils.createE("li",{
                paddingLeft:"40px",
                position:"relative"
            })
            if(!_subList[i].category){
                //如果当前菜单没有子菜单,则创建a标签,进行跳转
                let subA=Utils.createE("a",{
                    color:"#333",
                    textDecoration:"none",
                    width:"100%",
                    display:"inline-block"
                },{
                    textContent:_subList[i].name,
                    href:_subList[i].href || "javascript:void(0)",
                    target:_subList[i].href ? "_blank" : "_self"
                })
                Utils.appendTo(subA,subLi);
            }else{
                //如果当前菜单有子菜单,创建span标签
                let subSpan=Utils.createE("span",{
                    position:"absolute",
                    left:"20px",
                    top:"8px",
                    border: "1px solid #ccc",
                    display: "inline-block",
                    width: "10px",
                    height: "10px",
                    lineHeight:"8px"
                },{
                    textContent:_subList[i].category.length>0? "+" : "-"
                })
                subLi.textContent=_subList[i].name;
                Utils.appendTo(subSpan,subLi);
            }
            Utils.appendTo(subLi,subUl);
            //如果当前菜单没有子菜单,则跳过下面的执行
            if(!_subList[i].category) continue;
            //如果当前菜单有子菜单,将子菜单作为参数,进行递归
            this.createSubMenu(_subList[i].category,subLi);
        }
        Utils.appendTo(subUl,parent);
    }
    clickHandler(e){
        //如果当前点击的不是li标签或者span,直接跳出
        if(e.target.nodeName!=="LI" && e.target.nodeName!=="SPAN") return;
        let targ;
        //让targ等于当前点击的li标签
        if(e.target.nodeName==="SPAN") targ=e.target.parentElement;
        else targ=e.target;
        //如果当前点击Li下面没有子菜单,直接跳出
        if(targ.children.length<=1) return;
        //控制当前点击的Li下的ul显示隐藏
        if(!targ.bool) targ.lastElementChild.style.display="block";
        else targ.lastElementChild.style.display="none";
        targ.bool=!targ.bool;
        //改变span标签的内容
        this.changeSpan(targ);
    }
    changeSpan(elem){
    	//改变span的显示内容
        if(elem.lastElementChild.style.display==="block"){
            elem.firstElementChild.textContent="-";
        }else{
            elem.firstElementChild.textContent="+";
        }
    }
}

Utils.js文件,是一个工具包:

export default class Utils{
    static createE(elem,style,prep){
        elem=document.createElement(elem);
        if(style) for(let prop in style) elem.style[prop]=style[prop];
        if(prep) for(let prop in prep) elem[prop]=prep[prop];
        return elem;
    }
    static appendTo(elem,parent){
        if (parent.constructor === String) parent = document.querySelector(parent);
        parent.appendChild(elem);
    }
    static randomNum(min,max){
        return Math.floor(Math.random*(max-min)+min);
    }
    static randomColor(alpha){
        alpha=alpha||Math.random().toFixed(1);
        if(isNaN(alpha)) alpha=1;
        if(alpha>1) alpha=1;
        if(alpha<0) alpha=0;
        let col="rgba(";
        for(let i=0;i<3;i++){
            col+=Utils.randomNum(0,256)+",";
        }
        col+=alpha+")";
        return col;
    }
    static insertCss(select,styles){
        if(document.styleSheets.length===0){
            let styleS=Utils.createE("style");
            Utils.appendTo(styleS,document.head);
        }
        let styleSheet=document.styleSheets[document.styleSheets.length-1];
        let str=select+"{";
        for(var prop in styles){
            str+=prop.replace(/[A-Z]/g,function(item){
                return "-"+item.toLocaleLowerCase();
            })+":"+styles[prop]+";";
        }
        str+="}"
        styleSheet.insertRule(str,styleSheet.cssRules.length);
    }
    static getIdElem(elem,obj){
        if(elem.id) obj[elem.id]=elem;
        if(elem.children.length===0) return obj;
        for(let i=0;i<elem.children.length;i++){
            Utils.getIdElem(elem.children[i],obj);
        }
    }
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值