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

这个代码我删除了它底部的那个QQ,微博这些,只用了手风琴菜单部分,原版来源点击打开链接

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

function CreateList() {
	this.oWrap = document.createElement("div");//创建了一个div
	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 + ") <a href=\"" + project[i].href + "\" target=\"_blank\">" + project[i].text + "</a>"
                    //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()最初创建的那个div里 this.oWrap
			aData.shift()//删除原来的aData[0],以前的aData[1]就会变成现在的aData[0]
		}
		this.oWrap.id = "wrap";//为this.oWrap这个div加一个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: div#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<obj.offsetHeight
		obj.iSpeed = obj.iSpeed > 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的div的子类一遍,如果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,div,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>

猜你喜欢

转载自blog.csdn.net/qq_37473645/article/details/79672175