16.Vue技術棧開發實戰-可收縮多級菜單的實現


實現可收縮的側邊欄菜單。

效果展示

點擊收縮的效果。如果只有一級菜單



二級菜單

多級菜單的情況

展開的效果

多級菜單

開始

我們之前封裝的,我們的菜單要放在layout里

我們最后封裝的菜單組件,是要在sider里面

sider-menu組件

分別加sider-menu-submenu和side-menu-dropdown


另外兩個按鈕 值在sideMenu里面用,所以這里就不導出去了。光導出sideMenu

展開的時候用的iview的menu組件。
收起來用的是dropDown組件

它其實是一個個的按鈕圖標

所以在我們的組件最外層肯定是有一個控制,默認是menu。dropDown放在下面的div里面。

頂部需要一個logo



所以頂部的log位置是允許自定義內容的,所以我們想到可以用slot插槽。在最上面用slot插槽。如果 還有其他的插槽 可以在底部也放一個slot

展開是有狀態的,我們在layout組件內是有這么個狀態的。為true就是收縮。所以這個組件要把狀態傳進去。

所以我們在layout里面

調用組件,把屬性:collapsed加進去。

組件內定義collapsed屬性。默認是展開的。

menu展開的情況

每一條menu-item就是一個菜單

通過一個數組來渲染菜單。所以這個地方應該是用一個v-for去循環生成。我們如果在這里用v-for去循環的呢,只能循環出來一級

如果我們的層級是很多級呢?而且層級的多少是不確定的呢

我們之前講過一個遞歸組件的形式,所以這里地方我們就要用到遞歸組件。

在定義數據。用到iview里面的icon圖標



定義屬性叫做list。把這個list傳遞進去。

組件內定義屬性 list

默認如果是一個空數組,要在回調函數里面給它return 一個空的數組

上面是簡寫的形式,補全的寫法就是這種

如果要返回一個空對象呢,不能直接寫空對象,要用括號括起來。

最終我們默認是這樣的

要遞歸組件,外層用template

給沒一個menu都加上一個name的屬性

用menu的name值來做key。這里判斷item.children

這個可以也要給組件menu-item

menu-item上還需要一個nam的屬性

Submenu也需要name屬性。



最外層的div 寬度 要和父容器相等。

所以設置div的寬度是100%

菜單的寬度,來看下文檔,它可以設置一個width值


主題設置為dark,這樣北京顏色都是黑色了

有子菜單的情況

因為我們的層級是未知的,所以這里需要用到遞歸組件。
哪個部分是一直在循環下去的,就把誰拆出來 組裝成一個組件。這里很顯然,subMenu里面裹着menuItem。然后里面又有一個subMenu裹着menuItem。所以我們應該把subMenu拆出來,拆成遞歸組件。

我們在side-menu-submenu里面封裝。

起個名字叫做ReSubMenu

所以我們side-menu-submenu.vue改名叫做submenu

side-menu-dropdown.vue也改名re-dropdown.vue

應該把這整個對象傳給遞歸組件。

ReSubMenu引進來。

這個地方就改成re-submenu

組件定義了很多的條件和屬性的話,可以分行顯示、這樣比較清晰一些。

傳入當前的item對象當做數據。對組組件內部來說,它就是當前的父級。

遞歸組件內,定義parent屬性。

首先需要一個東西來作為插槽。顯示當前這個submenu的title

直接復制過來



這樣第一層就顯示出來,

接下來里面裹着的是menuItem

menuItem應該使用v-for渲染children里面的數組了

所以這里是個v-for

在side-menu里面,在遍歷的時候,是v-for循環一個template。在里面去判斷當前item有沒有children

這塊邏輯,在遞歸組件里面是復用的

所以這里復制過來,邏輯應該是一樣的

ist改成parent.children

遞歸組件,一定要給他一個name值。遞歸組件通過name值去調用他自身。


 
subMenu需要一個name的屬性。




為了好看,把標題的name改的短一點





side組件可以設置寬度。這里設置為300試一下

遞歸組件內,只定義了title沒有定義圖標







這里把所有的東西都包在了title里面

單獨的移除來

這樣 樣式就對了

再次強調遞歸組件的使用要領

組件里面,每一塊都是不斷的在重復下去的。那你就應該把每一部分拆成一個組件。當遞歸組件使用。

菜單收縮的功能

這里這么窄,用menuItem肯定是不行的。

先把上面的遞歸組件先注釋掉。這里還是用template循環list

沒有children的情況下的效果圖

完成用Tooltip。里面裹着我們的a標簽。

for循環沒個元素都要有key

現在a標簽都顯示在一排了。

所以需要給他一個樣式。width是1000%,同時設置它為塊級別的元素。

這個地方受了ToolTip的影響

為了不受tooltip的影響。加transfer屬性
a標簽的外面裹了,ivu-tooltip


把ivu-tooltip也設置成一個塊級選擇器。

這樣就換行了。

圖標顯示的有點小。size設置為20

圖標呢,希望是白色



tooltip的方向子設置在右邊


 
設置圖標居中。這樣圖標就居中了。

上下的padding,讓圖標之間有間隔

默認的狀態設置為收縮的狀態

子對象-dropdown遞歸組件封裝

定義屬性parent,返回默認還是一個空對象。

dropdown需要定義一個元素,是作為你鼠標觸發顯示的。把side-menu的a標簽復制過去。



把ReDropmdown引進來,然后使用這個組件。

同樣它也需要一個key,因為是v-for循環里面的

傳入parent屬性

報錯

這里加上v-if和v-else的判斷



DropdownMenu的 slot是list。里面用Template循環。



加上name屬性。

這里的圖標沒有居中

這里現在有菜單了

把title顯示出來



顯示在右邊,右邊開始的方向。

接下來顯示父界別的title,用span標簽去顯示。

發現第一級也顯示了title。我們希望的效果是菜單的第一級是不顯示title的

在里面顯示title。而且這里看不到有問題,這是因為之前設置的文字顏色為白色導致的。

這里把字體顏色白色去掉。不應該用css樣式去寫了 

第一級的icon顏色設置為白色。

icon-color設置為白色


多級里面的顏色為

遞歸組件內默認值就為灰色

傳入color為IconColor

里面是對的,但是文字顏色不太對。文字顏色應該和圖標的顏色是一樣的

因為我們是寫在a那標簽里面的,這里換成span標簽。那么就不用再單獨定義顏色了。

這里也換成span標簽,並且把class的類名改成drop-menu-span

css里面也修改為drop-menu-span

遞歸組件內也改

我們應該是讓第一級不顯示title,讓里面顯示title

也是和color一樣,我們傳入一個屬性

定義title的屬性。默認是true,顯示的

第一級菜單我們不顯示

然后控制Title的顯示

這里也顯示圖標

這里類型就是item.icon

第一級的圖標還是白色

color屬性改成這樣

具有字節別的菜單 居中的問題,所以居中的樣式我們要改變一下。如果showTitle為true的話,說不它不是第一級

不是第一級就偏左,否則的話就是居中

現在是偏左的,但是的話 我們應該給他一個padding-left

因為樣式比較復雜,所以我們直接寫在計算屬性里

return一個對象。



然后是一級菜單居中的效果。這里不能設置它的寬度是100%了。因為給這個ivu-dropdown類型設置為100%后,那么后面你這些子菜單是根據父元素的ivu-dropdown的類名 的寬度來定義的。 那你后面的寬度都這么寬了。

所以這里我們應該使用一個技巧。
最外層的div給它一個類名



給他設置為塊級別元素,然后marin:0 auto;居中



這樣菜單就好看多了

控制收縮和展開的狀態

把注釋的代碼都放開



展開

收縮

v-if和v-show的對比

都能實現對元素顯示和隱藏的控制
如果設置v-if為false。組件直接就不渲染了。
v-show為false,只是設置css為display為none,里面的內容實際都是渲染出來了。
所以當我們有時候會頻繁的切換show或者hide的時候,我們應該使用v-show.這樣就能減少我們性能的開銷。

所以這里我們要用v-show

添加事件

我們要知道,當前點擊的是哪一項。

把選中的name值打印一下




收縮的狀態下點擊事件

span綁定click事件,傳入item.name



dropdown綁定onclick事件





點擊這里,onclick事件觸發了兩次

因為我們的組件嵌套了多次。觸發了多個onclick事件

只希望觸發一次事件。如果當前不是第一級 輸出。


這樣就只處罰一次事件了

這里我們需要在這里拋出一個事件


這樣就沒有問題了 點擊事件


以上就算是封裝完成了。
 

代碼




 

結束

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM