1. 程式人生 > >學習例項索引原生js的手風琴選單 註釋詳解

學習例項索引原生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>