首页 > 其他分享 >vue3 + element plus实现侧边栏

vue3 + element plus实现侧边栏

时间:2022-10-02 10:08:36浏览次数:50  
标签:菜单 const text 侧边 element plus vue3 router 页面


一般前端项目少不了侧边栏。如图所示

vue3 + element plus实现侧边栏_ico


这些鬼东西特别繁琐,所以我们喜欢找些现成、开源的所谓后台管理的前端框架,开箱即用。方便是方便,而且做得还挺好,问题是,有学习成本,要按照它的规则行事。一些功能是怎么实现的,不清楚,除非研究它的源代码。想改的话,更不容易。一切都靠猜、盲测,一则不好改,二则出了问题也不知道是哪里的毛病,反而欲速则不达。

所以我们之前基于一个空白的vue项目开发,把需要的路由、ajax封装等摞上去。现在是实现侧边栏菜单。点击左侧菜单项,对应页面展示在右侧。下面是详细介绍,ui框架采用element plus。

1、如何编写侧边栏结构页面

html代码其实简单,左侧菜单用​​<el-menu>​​​,右侧展示使用​​<router-view>​​。后者不用做啥设置,点击菜单项,结果自然就展示在右侧了。好神奇。

以下是一个包含侧边栏的页面示例。支持二级菜单。三级或更多就不行了。

<template>
<el-container>
<el-aside width="255px"> <!-- 侧边栏宽255px -->
<!-- router是关键属性 -->
<el-menu
router
:default-active="to"
active-text-color="#ffd04b"
background-color="#001529"
text-color="#999"
class="el-menu-vertical-demo sliderHeight"
>
<!-- 如果菜单项存在子孙节点,使用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>
<!-- 结果展示在这里 -->
<router-view></router-view>
</el-main>
</el-container>
</template>

2、默认选中菜单及加载对应页面

很自然地,打开包含侧边栏结构的页面,应该有一个菜单项默认被选中,同时加载对应的页面。

但是element plus只提供了选中指定菜单功能,加载页面需要自己完成。

vue3 + element plus实现侧边栏_侧边栏结构页面_02

1)默认选中指定的菜单项
设置属性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)加载对应页面
elment plus只能设置选中菜单项,加载相应页面需要自己动手。

import { useRouter } from "vue-router";

const router = useRouter();
const gotoDefaultPage = (menus) => {
if (menus && menus.length > 0) {
const path = router.currentRoute.value.path;
//如果当前路径是子菜单,则直接打开子菜单;否则打开第一个子菜单
//页面中,使用了菜单项的route作为index
const to = path.split("/").length > 2 ? path : menus[0].route;
router.replace(to);
}
};

onMounted(() => {
const menus = getMenus();
gotoDefaultPage(menus);
});

3、刷新页面

好像刷新页面,选中啥的会丢失,页面一片空白?这个问题记得不是很清楚了,现在我没有这个问题。可能是获取到当前路由,按照路由重新打开。代码见2。

const path = router.currentRoute.value.path;
//如果当前路径是子菜单,则直接打开子菜单;否则打开第一个子菜单
//页面中,使用了菜单项的route作为index
const to = path.split("/").length > 2 ? path : menus[0].route;
router.replace(to);

4、icon

vue3 + element plus实现侧边栏_ico_03


每个菜单项前面有个小图标。图标应该在菜单项/路由表二合一的数据中定义。取值从elment plus的icon中选取。

数据结构

{
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>
<!-- 关键的一句 -->
<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、新开窗口

在侧边栏结构页面中,如何打开一个新窗口呢?

其实,无论是在普通页面,还是这种侧边栏结构页面,点击一个链接或按钮,打开一个新窗口,代码都是一样的。但是!里面用到了路由。如果该路由没有注册,那么在本文所示的侧边栏结构页面中,打开新窗口会失败,页面仍然显示在右侧,没有新开窗口!这一度让我很困惑,以为​​<router-view>​​​需要给个name,然而并没有什么卵用。按照本文所示的例子,侧边栏结构页面实际上有2个​​<router-view>​​​。一个是app.vue里设置了,然后侧边栏结构页面实际上是包含在外面这个​​<router-view>​​​中,然后它自己也有一个​​<router-view>​​​。两个都没有命名,那么都叫“default”。可能系统采取了就近原则,在侧边栏结构页面中点击新窗口链接,永远都对应它本身这个​​<router-view>​​。然而在定义路由项中,使用components,指定名称,不好使,一点用没有。后来我才发现,新开窗口的链接,或者说是路由,一定要注册,这样就能新开窗口了。

新开窗口的代码:

<template>
<div @click="browseIt(1000)" class="show-detail">打开明细页</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", //这里是跳转页面的name,要与路由设置保持一致
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: "页面一明细",
noList: true,
},
},

6、无限级菜单

前面的例子,菜单级别只能去到二级。如果要实现无限级,需要使用递归。页面组件递归。代码如下:

整体的侧边栏结构页面:

<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>



标签:菜单,const,text,侧边,element,plus,vue3,router,页面
From: https://blog.51cto.com/leftfist/5729201

相关文章

  • vue3动态路由及菜单
    一般来说,前端项目中的路由,很有可能是需要动态注册的。因为菜单可能在管理系统中维护,还跟权限绑定,用户登录以后,需要动态展示菜单。菜单往往跟路由挂钩,因此,路由需要动态注册。......
  • PDF-XChange Editor Plus
      ......
  • Mybatis plus代码生成器
    案例一demo为​​chenx/mybatisplus-demo​​​​参考​​​​案例​​项目初始结构数据库新建表项目配置启动CodeGenerator类中的main方式,输入表名,生成代码案例二demo为​......
  • Mybatis plus案例
    前言当表名为user时,会多生成2个实体类正常情况下生成的类测试是否可以直接在当前​​mybatis代码生成器的项目​​中开发启动项目后测试,发现当前项目只能用来生成代码即使项......
  • mybatis plus 项目模板
    前言​​案例地址​​项目搭建新建1个springboot项目,导入所需依赖点击查看详情<dependencies><dependency><groupId>org.springframework.boot</groupId>......
  • MyBatisPlus查询对象转QueryWrapper工具类
    技术背景在使用MyBatisPlus技术实际项目中,尤其是后台管理系统之类的项目中,经常会出现大量的需要将查询对象转换成QueryWrapper的应用场景,这时候就需要编写出现大量的转换代......
  • vue3 自定义指令控制按钮权限
    经过1个周的摸索和查阅资料,终于搞定VUE3中自定义指令,实现按钮级别的权限控制。当然,只是简单的对按钮进行隐藏和删除的dom操作比较容易,一直纠结的是当按钮无权限时,不是直接......
  • element-plus使用h和render函数,实现Service弹出Dialog
    在element-plus中,Messagebox和Message都实现了全局方法。但是Dialog就没有实现。本着自己动手丰衣足食的原则。自己动手写一个。定义一个ModalService.ts文件import{h......
  • vue element-ui 基本使用和按需加载的2种方式(推荐安装插件的方式)
    element-ui官网:https://element.eleme.cn/#/zh-CN/component/installation 安装npminstallelement-ui-S不太清楚这里为什么是-S的朋友可以看看我的这篇文章......
  • Component inside <Transition> renders non-element root node that cannot be anima
    原因是transition标签下存在多个根标签原代码:    解决方法  Suspense还处于试验阶段,可能导致default内容与fallback内容同时存在,导致错误......