欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

索引原生js的手风琴菜单注释详解(实例)

程序员文章站 2022-04-03 19:43:40
这个代码我删除了它底部的那个QQ,微博这些,只用了手风琴菜单部分 我还是个JS新手,可能注释很多地方都写得很邋遢,不简洁明了,有错误的地方也希望大家可以帮我指出来,修正我的思维误...

这个代码我删除了它底部的那个QQ,微博这些,只用了手风琴菜单部分

我还是个JS新手,可能注释很多地方都写得很邋遢,不简洁明了,有错误的地方也希望大家可以帮我指出来,修正我的思维误区,谢谢了。

function CreateList() {
	this.oWrap = document.createElement("p");//创建了一个p
	this.initialize.apply(this, arguments);//initialize 只不过是个变量,代表一个方法,叫什么名字都行。
    this.click.call(this);//click也只是一个变量,代表一个方法,叫什么名字都行
    /* call和apply的第一个实参是要调用函数的母对象,call方法是将所有参数罗列出来,而apply是将所有参
    数放在一个数组中。这里有篇文章可以看看:https://blog.csdn.net/myhahaxiao/article/details/6952321*/
}
 /*这是另一篇有注释里写到的:www.bubuko.com/infodetail-1164722.html
         arguments就是构造函数接受的参数,构造函数调用时
         new CreateList(aData[])传入的是一个数组
         数组的每一个项都是json对象
          json对象的格式为
             project:[
                    {
                         text:"测试文字",                     
                     },
                     {
                         text:"测试文字",
                         href:""
                     }
                  ]
         每一个project数组的项对应一个DL----(对应无序列表的ul)-----自定义列表dl---dt--dd
*/
/*prototype 原型对象的作用,就是定义所有实例对象共享的属性和方法  相关文章:https://blog.csdn.net/jasonzds/article/details/53706958*/
CreateList.prototype = {
	initialize: function(aData) {	//这个函数的主要目的是初始化 把dl dt dd 的数量、结构层次这些弄好	
		var oDl, oElem, project, i;
		while(aData[0]) {//aData[0]为真时,循环执行,代码往后走有一个aData.shift(),shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
			oDl = document.createElement("dl");
			project = aData[0].project;	
			for(i = 0; i < project.length; i++) {//从project遍历出新建dl下的dt和dd
				if(project[i].href) {//有href属性的为dd
					oElem = document.createElement("dd");
					oElem.innerHTML = i + ") " + project[i].text + ""
                    //innerHTML 添加内容
                }
				else {//反之为dt
					oElem = document.createElement("dt");
					oElem.innerHTML = project[i].text + " (" + (project.length - 1) + ")"	
				}
				oDl.appendChild(oElem);//将oElem加入到oDl里,也就是把dt dd放在dl里
				oDl.style.height = "31px"//将dl的高度设为31px;
			}
			this.oWrap.appendChild(oDl);//将新建的dl放到CreateList()最初创建的那个p里 this.oWrap
			aData.shift()//删除原来的aData[0],以前的aData[1]就会变成现在的aData[0]
		}
		this.oWrap.id = "wrap";//为this.oWrap这个p加一个id wrap
		document.body.appendChild(this.oWrap);//再将其加入到body里
	},
	click: function() {//这个函数主要是点击事件
		var that = this;
		this.oWrap.onclick = function(event) {//点击事件的绑定
			var oEv, oTarget, oParent, i;
			oEv = event || window.event;//在FireFox浏览器中,事件绑定的函数要获取到事件本身,需要从函数中传入,而IE等浏览器则可以直接使用event或者window.event得到事件本身。
            oTarget = oEv.target || oEv.srcElement;//返回事件的目标节点,根据console.log(oTarget);可以得到该节点是dt
			oParent = oTarget.parentElement || oTarget.parentNode;//事件的目标节点的父节点,dl
			oParent.height = function() {//获取dl里的总高度
				var iHeight = 0;//在这里用console.log( oParent.children[0].offsetHeight)==31其他的都是26 主要原因是要理解到offsetHeight的定义 然后去看css就知道为什么了
                //HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数。
                for(i = 0;i < oParent.children.length; i++) iHeight += oParent.children[i].offsetHeight;
				return iHeight;//iHeight=dt像素高度+所有dd像素高度
			}();
			if(oTarget.tagName.toUpperCase() == "DT") {//如果是dt,当你的菜单是展开时,点dd就不会执行这段代码
				var aSiblings = that.siblings(oParent), count, i;//siblings()往下翻,代码最后一个函数
                for(count = i = 0; i < aSiblings.length; i++) {//对非点击的dl元素进行遍历,记住这里有一个循环,也就是为什么会有++count== aSiblings.length的原因
                    //第一个参数是dl 第二个是点击元素dt的像素高度 第三个是运动类型 第四个是匿名函数
                    //这个startMove是检测其他dl是否展开,如果展开就要对其进行收拢的操作
                    //匿名函数!=自执行匿名函数,匿名函数作为参数,在调用(将匿名函数作为参数的)函数里被调用执行了。
					that.startMove(aSiblings[i], oTarget.offsetHeight, "buffer", function() {
                        this.children[0].className = "";//这里的this代表的是aSiblings[i],也就是dl
                        //这个if语句是对点击的dl进行操作
						if(++count == aSiblings.length) {//当除点击事件在的dl所有dl的类名都为空时
							if(oParent.offsetHeight == oTarget.offsetHeight) {//当点击事件所在菜单没有没有展开时
                                oTarget.className = "current";
                                //这个startMove是把点击事件所在菜单被展开
                                //看清第二个是传的参数是oParent.height
								that.startMove(oParent, oParent.height, "flex")
							}
							else {//当点击事件所在菜单展开时,这个startMove就把他收拢
								that.startMove(oParent, oTarget.offsetHeight, "buffer", function() {
									oTarget.className = ""	;
								})
							}								
						}	
					})
				}
			}
		}
	},
	startMove: function(obj, iTarget, type, callback) {
		var that = this;//这里的this 是指CreateList?{oWrap: p#wrap}
		clearInterval(obj.timer);
		obj.iSpeed = 0;
		obj.timer = setInterval(function() {
			that[type].call(that, obj, iTarget, callback)
		}, 30)
	},
	buffer: function(obj, iTarget, callback) {//菜单的收拢
		obj.iSpeed = (iTarget - obj.offsetHeight) / 5;//(1)当前没有任何菜单展开 或 点击的是菜单展开事件的dt时 iTarget==obj.offsetHeight,(2)有菜单的话(不为点击事件本来所在菜单),当循环到展开的那个菜单时iTarget 0 ? Math.ceil(obj.iSpeed) : Math.floor(obj.iSpeed);
		obj.offsetHeight == iTarget ? (clearInterval(obj.timer), callback && callback.call(obj)) : obj.style.height = obj.offsetHeight + obj.iSpeed + "px"
        //是第(1)种情况的时候,clearInterval(obj.timer) 被调用,if(callback){callback.call(obj)}
        //是第(2)种情况的时候,会一直到obj.offsetHeight == iTarget,也就是另一个菜单被收拢,clearInterval(obj.timer) 才会被调用,并if(callback){callback.call(obj)}
    },
	flex: function(obj, iTarget, callback) {//打开菜单
		obj.iSpeed += (iTarget - obj.offsetHeight) / 6;
		obj.iSpeed *= 0.75;
		if(Math.abs(iTarget - obj.offsetHeight) <= 1 && Math.abs(obj.iSpeed) <= 1) {/*abs() 方法可返回数的绝对值。*/
			clearInterval(obj.timer);
			obj.style.height = iTarget + "px";
			callback && callback.call(obj);//不要这一句程序也是正确的,不知道这句拿来做什么
		}
		else {
			obj.style.height = obj.offsetHeight + obj.iSpeed + "px";
		}
	},
	siblings: function(element) {//这个函数就是找到所有的同级元素,并且返回一个数组
        var aTmp = [], oParent = element.parentElement || element.parentNode, i;
        //这个for语句的意思是遍历,id为wrap的p的子类一遍,如果element != oParent.children[i],然后就把它放进 aTmp[]中,最后返回aTmp[]
		for(i = 0; i < oParent.children.length; i++) element != oParent.children[i] && aTmp.push(oParent.children[i]);
		return aTmp
	}
};

html,css,js

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <title>手风琴菜单</title>  
    <style>  
    body,p,dl,dt,dd{margin:0;padding:0;}  
    a:link,a:visited{color:#FFF;text-decoration:none;}  
    a:hover{text-decoration:underline;}  
    #wrap{width:350px;background:#FFF;border:12px solid #EEE;border-radius:10px;margin:10px auto 0;padding:5px 5px 4px;}  
    #wrap dl{color:#FFF;overflow:hidden;background:#7CF;}  
    #wrap dt,#wrap dd{padding-left:15px;border-bottom:1px solid #FFF;}  
    #wrap dt{cursor:pointer;font-size:14px;background:#9C0;font:700 14px/30px Tahoma;}  
    #wrap dt.current{background:#09F;}  
    #wrap dd{background:#7CF;font:12px/25px Tahoma;}/*前者是font-size,后者是line-height*/  
    </style>  
    <script src="js/CreateList.js"></script>  
    <script>  
    window.onload = function() {  
        new CreateList([  
        {  
            project: [{  
                text: "标题1"  
            },  
            {  
                text: "1",  
                href: "1"  
            },  
            {  
                text: "2",  
                href: "2"  
            }]  
        },  
        {  
            project: [{  
                text: "标题2"  
            },  
            {  
                text: "1",  
                href: "1"  
            },  
            {  
                text: "2",  
                href: "2"  
            },  
            {  
                text: "3",  
                href: "3"  
            },  
            {  
                text: "4",  
                href: "4"  
            },]  
        },  
        {  
            project: [{  
                text: "标题3"  
            },  
            {  
                text: "1",  
                href: "1"  
            },  
            {  
                text: "2",  
                href: "2"  
            },  
            {  
                text: "3",  
                href: "3"  
            },  
            {  
                text: "4",  
                href: "4"  
            },]  
        },  
        {  
            project: [{  
                text: "标题4"  
            },  
            {  
                text: "1",  
                href: "1"  
            },  
            {  
                text: "2",  
                href: "2"  
            },  
            {  
                text: "3",  
                href: "3"  
            },  
            {  
                text: "4",  
                href: "4"  
            },]  
        }  
        ]);  
         
    };  
</script>  
</head>  
<body></body>  
      
</html>