實現可收縮的側邊欄菜單。
效果展示
點擊收縮的效果。如果只有一級菜單
二級菜單
多級菜單的情況
展開的效果
多級菜單
開始
我們之前封裝的,我們的菜單要放在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事件
只希望觸發一次事件。如果當前不是第一級 輸出。
這樣就只處罰一次事件了
這里我們需要在這里拋出一個事件
這樣就沒有問題了 點擊事件
以上就算是封裝完成了。
代碼
結束