vue3+element?plus實現(xiàn)側(cè)邊欄過程
一般前端項目少不了側(cè)邊欄。
如圖所示
這些鬼東西特別繁瑣,所以我們喜歡找些現(xiàn)成、開源的所謂后臺管理的前端框架,開箱即用。
方便是方便,而且做得還挺好,問題是,有學(xué)習(xí)成本,要按照它的規(guī)則行事。一些功能是怎么實現(xiàn)的,不清楚,除非研究它的源代碼。
想改的話,更不容易。一切都靠猜、盲測,一則不好改,二則出了問題也不知道是哪里的毛病,反而欲速則不達(dá)。
所以我們之前基于一個空白的vue項目開發(fā),把需要的路由、ajax封裝等摞上去?,F(xiàn)在是實現(xiàn)側(cè)邊欄菜單。點擊左側(cè)菜單項,對應(yīng)頁面展示在右側(cè)。
下面是詳細(xì)介紹,ui框架采用element plus。
1、如何編寫側(cè)邊欄結(jié)構(gòu)頁面
html代碼其實簡單,左側(cè)菜單用<el-menu>
,右側(cè)展示使用<router-view>
。
后者不用做啥設(shè)置,點擊菜單項,結(jié)果自然就展示在右側(cè)了。好神奇。
以下是一個包含側(cè)邊欄的頁面示例。支持二級菜單。
三級或更多就不行了。
<template> <el-container> <el-aside width="255px"> <!-- 側(cè)邊欄寬255px --> <!-- router是關(guān)鍵屬性 --> <el-menu router :default-active="to" active-text-color="#ffd04b" background-color="#001529" text-color="#999" class="el-menu-vertical-demo sliderHeight" > <!-- 如果菜單項存在子孫節(jié)點,使用el-sub-menu --> <el-sub-menu v-if="item.children" :index="item.route"> <template #title> <el-icon><component :is="item.icon"></component></el-icon>{{ item.text }} </template> <el-menu-item v-for="item2 in item.children" :key="item2.name" :index="item2.route" > <template #title> <el-icon><component :is="item2.icon"></component></el-icon >{{ item2.text }} </template> </el-menu-item> </el-sub-menu> <!-- 否則使用el-menu-item --> <el-menu-item v-else :index="item.route"> <template #title> <el-icon><component :is="item.icon"></component></el-icon>{{ item.text }} </template> </el-menu-item> </el-menu> </el-aside> <el-main> <!-- 結(jié)果展示在這里 --> <router-view></router-view> </el-main> </el-container> </template>
2、默認(rèn)選中菜單及加載對應(yīng)頁面
很自然地,打開包含側(cè)邊欄結(jié)構(gòu)的頁面,應(yīng)該有一個菜單項默認(rèn)被選中,同時加載對應(yīng)的頁面。
但是element plus只提供了選中指定菜單功能,加載頁面需要自己完成。
1)默認(rèn)選中指定的菜單項
設(shè)置屬性el-menu.default-active。
屬性值是el-sub-menu.index
或el-menu-item.index
<el-menu router :default-active="to" active-text-color="#ffd04b" background-color="#001529" text-color="#999" class="el-menu-vertical-demo sliderHeight" >
<el-menu-item :index="item.route">
2)加載對應(yīng)頁面
elment plus只能設(shè)置選中菜單項,加載相應(yīng)頁面需要自己動手。
import { useRouter } from "vue-router"; const router = useRouter(); const gotoDefaultPage = (menus) => { if (menus && menus.length > 0) { const path = router.currentRoute.value.path; //如果當(dāng)前路徑是子菜單,則直接打開子菜單;否則打開第一個子菜單 //頁面中,使用了菜單項的route作為index const to = path.split("/").length > 2 ? path : menus[0].route; router.replace(to); } }; onMounted(() => { const menus = getMenus(); gotoDefaultPage(menus); });
3、刷新頁面
好像刷新頁面,選中啥的會丟失,頁面一片空白?這個問題記得不是很清楚了,現(xiàn)在我沒有這個問題。
可能是獲取到當(dāng)前路由,按照路由重新打開。代碼見2。
const path = router.currentRoute.value.path; //如果當(dāng)前路徑是子菜單,則直接打開子菜單;否則打開第一個子菜單 //頁面中,使用了菜單項的route作為index const to = path.split("/").length > 2 ? path : menus[0].route; router.replace(to);
4、icon
每個菜單項前面有個小圖標(biāo)。圖標(biāo)應(yīng)該在菜單項/路由表二合一的數(shù)據(jù)中定義。取值從elment plus的icon中選取。
- 數(shù)據(jù)結(jié)構(gòu)
{ path: "p3-1", name: "p3-1", component: () => import("../views/module3/page1"), meta: { text: "頁面A", icon: "Histogram", }, },
- 頁面
<el-menu-item :index="item.route"> <template #title> <el-icon> <!-- 關(guān)鍵的一句 --> <component :is="item.icon"></component> </el-icon>{{ item.text }} </template> </el-menu-item>
因為可以使用任意的element plus的icon,所以索性全局注冊
- src/main.js
import { createApp } from "vue"; import App from "./App.vue"; 。。。 import ElementPlus from "element-plus"; import "element-plus/dist/index.css"; import * as ElIcons from "@element-plus/icons-vue"; const app = createApp(App); app.use(ElementPlus).mount("#app"); for (const name in ElIcons) { app.component(name, ElIcons[name]); }
5、新開窗口
在側(cè)邊欄結(jié)構(gòu)頁面中,如何打開一個新窗口呢?
其實,無論是在普通頁面,還是這種側(cè)邊欄結(jié)構(gòu)頁面,點擊一個鏈接或按鈕,打開一個新窗口,代碼都是一樣的。
但是!里面用到了路由。
如果該路由沒有注冊,那么在本文所示的側(cè)邊欄結(jié)構(gòu)頁面中,打開新窗口會失敗,頁面仍然顯示在右側(cè),沒有新開窗口!
這一度讓我很困惑,以為<router-view>
需要給個name,然而并沒有什么卵用。
按照本文所示的例子,側(cè)邊欄結(jié)構(gòu)頁面實際上有2個<router-view>
。
一個是app.vue里設(shè)置了,然后側(cè)邊欄結(jié)構(gòu)頁面實際上是包含在外面這個<router-view>
中,然后它自己也有一個<router-view>
。
兩個都沒有命名,那么都叫“default”??赡芟到y(tǒng)采取了就近原則,在側(cè)邊欄結(jié)構(gòu)頁面中點擊新窗口鏈接,永遠(yuǎn)都對應(yīng)它本身這個<router-view>
。
然而在定義路由項中,使用components,指定名稱,不好使,一點用沒有。后來我才發(fā)現(xiàn),新開窗口的鏈接,或者說是路由,一定要注冊,這樣就能新開窗口了。
- 新開窗口的代碼:
<template> <div @click="browseIt(1000)" class="show-detail">打開明細(xì)頁</div> <div> <router-link target="_blank" to="p2-1/detail/999" >第一種新窗口打開頁面</router-link > </div> </template> <script> import { reactive } from "vue"; import { useRouter } from "vue-router"; //引入useRouter export default { setup() { const router = useRouter(); const browseIt = (id) => { const to = router.resolve({ name: "p2-1-detail", //這里是跳轉(zhuǎn)頁面的name,要與路由設(shè)置保持一致 params: { id: id }, }); window.open(to.href, "_blank"); }; return { browseIt, }; }, }; </script>
- 路由
{ path: "p2-1/detail/:id", name: "p2-1-detail", component: () => import("../views/module2/page-1-detail.vue"), meta: { text: "頁面一明細(xì)", noList: true, }, },
6、無限級菜單
前面的例子,菜單級別只能去到二級。如果要實現(xiàn)無限級,需要使用遞歸。頁面組件遞歸。
代碼如下:
- 整體的側(cè)邊欄結(jié)構(gòu)頁面:
<template> <el-container> <el-aside width="255px"> <el-menu router :default-active="to" active-text-color="#ffd04b" background-color="#001529" text-color="#999" class="el-menu-vertical-demo sliderHeight" > <template v-for="item in menus" :key="item.name"> <!-- 自定義的菜單組件 --> <middle-menu :item="item"></middle-menu> </template> </el-menu> </el-aside> <el-main> <router-view></router-view> </el-main> </el-container> </template> <script> import MiddleMenu from "./SidebarMenu.vue"; </script>
- 自定義的菜單組件
<template> <el-sub-menu v-if="item.children" :index="item.route"> <template #title> <el-icon><component :is="item.icon"></component></el-icon >{{ item.text }}</template > <template v-for="innerItem in item.children" :key="innerItem.name"> <!-- 遞歸 --> <middle-menu :item="innerItem"></middle-menu> </template> </el-sub-menu> <el-menu-item v-else :index="item.route"> <template #title> <el-icon><component :is="item.icon"></component></el-icon>{{ item.text }} </template> </el-menu-item> </template> <script> import { defineComponent } from "vue"; export default defineComponent({ name: "middle-menu", props: { item: { type: Object, required: true, }, }, }); </script>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue.js實現(xiàn)請求數(shù)據(jù)的方法示例
這篇文章主要給大家介紹了vue.js實現(xiàn)請求數(shù)據(jù)的方法示例,文中分別介紹了vue1.0和vue2.0的示例方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-02-02element-ui中el-row中設(shè)置:gutter間隔不生效問題
這篇文章主要介紹了element-ui中el-row中設(shè)置:gutter間隔不生效問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08如何利用vue實現(xiàn)登陸界面及其跳轉(zhuǎn)詳解
在開發(fā)中我們經(jīng)常遇到這樣的需求,需要用戶直接點擊一個鏈接進(jìn)入到一個頁面,下面這篇文章主要給大家介紹了關(guān)于如何利用vue實現(xiàn)登陸界面及其跳轉(zhuǎn)的相關(guān)資料,需要的朋友可以參考下2023-04-04WebStorm啟動vue項目報錯代碼:1080?throw?err解決辦法
在使用webstorm新建vue項目時常會遇到一些報錯,下面這篇文章主要給大家介紹了關(guān)于WebStorm啟動vue項目報錯代碼:1080?throw?err的解決辦法,文中將解決辦法介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12