手風(fēng)琴菜單
在寫后臺(tái)管理頁面的時(shí)候,編寫折疊菜單是一個(gè)比較常見的應(yīng)用場(chǎng)景。那么今天我們就來學(xué)習(xí)一下怎么使用各種姿勢(shì)寫出手風(fēng)琴式的折疊菜單。
寫之前先看一下效果,插件來源于jQuery之家,演示效果可以點(diǎn)擊這里折疊菜單。jquery之家的源碼好像有點(diǎn)問題,下載可以點(diǎn)這里。
折疊效果的原理
其實(shí)寫出這個(gè)折疊展開的效果并不復(fù)雜,用原生的js代碼就可以實(shí)現(xiàn)。首先看一下html結(jié)構(gòu)和樣式:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>折疊菜單</title>
<style>
.toggle{
overflow: hidden;
height: 0;
transition: height 1s;
}
</style>
</head>
<body>
<div>
<h4 class="unfold">我愛</h4>
<ul class="toggle">
<li>哈士奇</li>
<li>大金毛</li>
<li>薩摩耶</li>
</ul>
</div>
</body>
</html>
h4標(biāo)簽就是我們的一級(jí)菜單,ul里面的子項(xiàng)就是我們的二級(jí)菜單。我們給子菜單設(shè)置了高度為0和overflow: hidden,這樣設(shè)置后子菜單是默認(rèn)隱藏的,接下來只要我們只要在js中調(diào)整ul的高度就可以了。
原生js實(shí)現(xiàn)折疊效果
對(duì)于上面的這種html結(jié)構(gòu),其實(shí)代碼很簡(jiǎn)單。
var btn=document.getElementsByClassName("unfold")[0];
var items=document.getElementsByClassName("toggle")[0];
btn.onclick=function () {
items.style.height="70px";
};
由于這里只是簡(jiǎn)單的講解原理,所以沒有考慮各種復(fù)雜的情況。
jq實(shí)現(xiàn)折疊效果
jq已經(jīng)幫我們封裝好了slideToggle()方法,這個(gè)方法可以實(shí)現(xiàn)點(diǎn)擊展開,再次點(diǎn)擊收回的效果,所以我們直接使用這個(gè)方法就可以了,下面是代碼:
var domMenus=$(".menu");
domMenus.on("click",function () {
$(this).next().slideToggle();
})
這里簡(jiǎn)單的說下jquery的slideToggle方法,在點(diǎn)擊之前,它將二級(jí)菜單設(shè)置為display:none,在點(diǎn)擊后馬上將二級(jí)菜單設(shè)置為display:block;overflow:hidden;height:0,接著再不停的增加高度,當(dāng)高度等于二級(jí)菜單,也就是ul的實(shí)際高度時(shí),停止增加高度,然后移除這些屬性,只保留display:block這個(gè)屬性。
組件化的實(shí)現(xiàn)
直接像我們上面這么寫的確可以實(shí)現(xiàn)效果,但是對(duì)于代碼的復(fù)用以及功能的可定制性都比較差,并且暴露了太多的自定義變量,所以我們要對(duì)代碼進(jìn)行重構(gòu)。下面這段代碼來自于上面提到的插件源碼,源碼中變量的命名語義化比較差,所以我對(duì)變量重新命名,方便大家觀看。
對(duì)于html和css中比較重要的部分我簡(jiǎn)單的介紹一下,下面的這些內(nèi)容也請(qǐng)結(jié)合上面提到的插件源碼觀看。
html部分請(qǐng)?jiān)跒g覽器中自行觀看,不再講解,css部分有幾個(gè)比較重要的樣式:
.submenu {
display: none;
}
.accordion li.open .link {
color: #b63b4d;
}
.accordion li.open i {
color: #b63b4d;
}
.accordion li.open i.fa-chevron-down {
transform: rotate(180deg);
}
第一個(gè)是讓二級(jí)子菜單默認(rèn)隱藏,第二個(gè)的意思是,在li有open這個(gè)樣式類時(shí),.link的color屬性變?yōu)?code>color: #b63b4d;,剩下的2個(gè)同上。
接著我們?cè)賮砜磈s部分:
var Accorrdian=function (menusWrap,multiple) {
this.menusWrap=menusWrap;
this.multiple=multiple|| false;
var links=menusWrap.find('.link');
links.on("click",{menusWrap:menusWrap,multiple:this.multiple},this.dropdown);
};
Accorrdian.prototype.dropdown=function (event) {
var menusWrap=event.data.menusWrap;
var domLink=$(this);
var menuItems=domLink.next();
menuItems.slideToggle();
domLink.parent().toggleClass('open');
if(!event.data.multiple){
menusWrap.find('.submenu').not(menuItems).slideUp().parent().removeClass('open');
}
};
var accordion=new Accorrdian($('#accordion'),false);
首先我們從整體上來看這段代碼,這段代碼首先定義了一個(gè)Accorrdian的構(gòu)造函數(shù),然后在這個(gè)構(gòu)造函數(shù)的原型上定義了一個(gè)dropdown的方法。最后新建了一個(gè)Accorrdian的對(duì)象,參數(shù)有2個(gè)。第一個(gè)參數(shù)是一個(gè)jquery的dom對(duì)象,它包裹著所有一級(jí)菜單,第二個(gè)參數(shù)是用來設(shè)置每次點(diǎn)擊的時(shí)候能展開的二級(jí)菜單的數(shù)量,如果為false,則每次只能有一個(gè)二級(jí)菜單展開,為true則不做限制。
現(xiàn)在看一下這個(gè)構(gòu)造函數(shù):
this.multiple=multiple|| false;
這條語句很有意思,利用了||運(yùn)算符的特性,當(dāng)前面一個(gè)值為真時(shí),不再對(duì)后面的值(代碼)作判斷(執(zhí)行)。所以這段代碼的意思是當(dāng)multiple這個(gè)值不為空時(shí),this.multiple=multiple,當(dāng)multiple為空時(shí),this.multiple=false。一句話來說就是給multiple設(shè)置了一個(gè)默認(rèn)值false。
接著找到menusWrap下的所有.link,也就是所有的一級(jí)菜單,然后給這些一級(jí)菜單注冊(cè)了一個(gè)點(diǎn)擊事件,每次點(diǎn)擊就執(zhí)行一次dropdown方法。但是這段注冊(cè)事件的代碼有點(diǎn)特殊:
links.on("click",{menusWrap:menusWrap,multiple:this.multiple},this.dropdown);
它的參數(shù)有三個(gè),第二個(gè)參數(shù)是一個(gè)對(duì)象,它會(huì)傳給第三個(gè)參數(shù),也就是dropdown方法中,我們可以在第三個(gè)參數(shù),dropdown方法中取出這個(gè)參數(shù),這個(gè)數(shù)據(jù)是掛靠在event對(duì)象的data屬性上,下面的這段代碼就是取出這第二個(gè)參數(shù):
var menusWrap=event.data.menusWrap;
然后我們?cè)倏磀ropdown這個(gè)方法,首先它找到當(dāng)前被點(diǎn)擊的這個(gè)一級(jí)菜單的下一個(gè)dom節(jié)點(diǎn),也就是這個(gè)一級(jí)菜單對(duì)應(yīng)的二級(jí)菜單,然后對(duì)這個(gè)二級(jí)菜單執(zhí)行
slideToggle()方法,接著再給這個(gè)一級(jí)菜單添加opne樣式類,改變一級(jí)菜單的樣式。然后我們?cè)倏匆幌伦詈筮@個(gè)if語句:
if(!event.data.multiple){
menusWrap.find('.submenu').not(menuItems).slideUp().parent().removeClass('open');
}
這里首先判斷我們新建對(duì)象的時(shí)候第二個(gè)參數(shù)是true還是false,如果是true不再執(zhí)行,如果是false則開始執(zhí)行代碼。首先它找到所有的二級(jí)菜單,當(dāng)前被點(diǎn)擊的一級(jí)菜單對(duì)應(yīng)的二級(jí)菜單除外,然后對(duì)這些所有的二級(jí)菜單執(zhí)行slideUp方法,也就是將所有的二級(jí)菜單收起。
至此,一個(gè)可定制可復(fù)用的折疊菜單插件已經(jīng)完成了。