各種姿勢(shì)教你寫手風(fēng)琴式折疊菜單

手風(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è)的意思是,在liopen這個(gè)樣式類時(shí),.linkcolor屬性變?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)完成了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容