Vue实训---4-使用Pinia实现menu菜单展示/隐藏
0.menu菜单展示/隐藏实现方法
Menu 菜单 | Element Plus中,当:collapse="isCollapse"其中isCollapse的值为true时菜单栏隐藏,当isCollapse的值为false时菜单栏显示。接下来使用pinia实现CommonAside.vue和CommonHeader.vue组件之间数据的共享,即点击CommonHeader.vue组件中的mune按钮,展示隐藏CommonAside.vue组件中的菜单栏。
1.pinia简介
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。简介 | Pinia
2.pinia安装
在vscode终端中输入: npm install pinia
3.在main.js中使用pinia
// 引入 pinia
import { createPinia } from 'pinia'
// 创建 pinia 实例
const pinia = createPinia()
// 注入 pinia
app.use(pinia)
4.在src文件夹下创建stores文件夹,在其中创建index.js并编写代码
import { defineStore } from "pinia";
import { ref, computed, reactive } from "vue";
// // https://pinia.vuejs.org/zh/core-concepts/ 官方文档示例代码
// // 定义 store 的一种语法。我们可以传入一个函数,该函数定义了一些响应式属性和方法,并且返回一个带有我们想暴露出去的属性和方法的对象。
// // 创建一个 store
// export const useAllDateStore = defineStore("allDate", () => {
// // 定义响应式属性
// const isCollapse = ref(false);
// // // 定义方法来切换布尔值
// function toggleCollapse() {
// isCollapse.value = !isCollapse.value;
// }
// // 返回 store 对象
// return {
// isCollapse,
// toggleCollapse,
// };
// // const count = ref(0)
// // const doubleCount = computed(() => count.value * 2)
// // function increment() {
// // count.value++
// // }
// // return { count, doubleCount, increment }
// });
// 你可以认为 state 是 store 的数据 (data),getters 是 store 的计算属性 (computed),而 actions 则是方法 (methods)。
export const useAllDateStore = defineStore("allDate", {
state: () => ({
isCollapse: false,
// count: 0,
// name: "Eduardo",
}),
getters: {
// doubleCount: (state) => state.count * 2,
},
actions: {
toggleCollapse() {
this.isCollapse = !this.isCollapse;
},
},
});
5.修改CommonAside.vue
我们要在组件间传递的值是“isCollapse”,修改CommonAside.vue:
CommonAside.vue所有代码:
<template>
<!-- 首先最外层是Main.vue中注释的<el-aside width="200px" class="el-aside">Aside</el-aside>,我们将侧边栏改成我们自定义的组件,通过common-aside引入我们自己写的组件 -->
<el-aside :width="width" class="el-aside">
<el-menu background-color="#545c64" text-color="#fff" :collapse="isCollapse">
<!-- 写菜单栏的大标题————通用后台管理系统 -->
<h3 v-show="!isCollapse">通用后台管理系统</h3>
<h3 v-show="isCollapse">后台</h3>
<!-- 循环遍历菜单栏 -->
<!-- 1.没有子菜单的遍历 -->
<el-menu-item v-for="item in noChildren" :key="item.path" :index="item.path">
<!-- <el-icon><icon-menu /></el-icon> -->
<!-- 动态获取icon图标 -->
<component :is="item.icon" class="icons"></component>
<!-- 显示文字内容 -->
<span>{{ item.label }}</span>
</el-menu-item>
<!-- 2.有子菜单的遍历 -->
<el-sub-menu v-for="item in hasChildren" :key="item.path" :index="item.path">
<template #title>
<!-- 动态获取icon图标 -->
<component :is="item.icon" class="icons"></component>
<!-- 显示文字内容 -->
<span>{{ item.label }}</span>
</template>
<!-- 分组 -->
<el-menu-item-group>
<!-- 循环遍历子菜单 -->
<el-menu-item v-for="child in item.children" :key="child.path" :index="child.path">
<!-- 动态获取icon图标 -->
<component :is="child.icon" class="icons"></component>
<!-- 显示文字内容 -->
<span>{{ child.label }}</span>
>
</el-menu-item>
</el-menu-item-group>
</el-sub-menu>
</el-menu>
</el-aside>
</template>
<script setup>
import { ref, computed } from 'vue'
import { storeToRefs } from 'pinia';
import { useAllDateStore } from '@/stores/index';
// 获取 store 实例
const store = useAllDateStore();
// 使用 storeToRefs 解构响应式属性
const { isCollapse } = storeToRefs(store);
// 根据 isCollapse 来计算宽度
const width = computed(() => isCollapse.value ? '64px' : '200px')
const list = ref([
{
path: '/home',
name: 'home',
label: '首页',
icon: 'house',
url: 'Home'
},
{
path: '/mall',
name: 'mall',
label: '商品管理',
icon: 'video-play',
url: 'Mall'
},
{
path: '/user',
name: 'user',
label: '用户管理',
icon: 'user',
url: 'User'
},
{
path: 'other',
label: '其他',
icon: 'location',
children: [
{
path: '/page1',
name: 'page1',
label: '页面1',
icon: 'setting',
url: 'Page1'
},
{
path: '/page2',
name: 'page2',
label: '页面2',
icon: 'setting',
url: 'Page2'
}
]
}
])
const noChildren = computed(() => list.value.filter(item => !item.children))
const hasChildren = computed(() => list.value.filter(item => item.children))
</script>
<style lang="less" scoped>
.icons {
width: 18px;
height: 18px;
margin-right: 5px;
}
.el-menu {
border-right: none;
h3 {
line-height: 48px;
color: #fff;
text-align: center;
}
}
.el-aside {
height: 100%;
background-color: #545c64;
}
</style>
6.修改CommonHeader.vue
CommonHeader.vue完整代码:
<template>
<div class="header">
<!-- 左侧点击四个点的Menu按钮具有折叠菜单栏的功能,右侧user的头像,头像有下栏菜单 -->
<div class="l-content">
<el-button size="small" @click="toggleCollapse">
<component class="icons" is="menu"></component>
</el-button>
<el-breadcrumb separator="/" class="bread">
<el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="r-content"> <el-dropdown>
<span class="el-dropdown-link">
<!-- Dropdown List
<el-icon class="el-icon--right">
<arrow-down />
</el-icon> -->
<!-- 将此部分内容换成我们要显示的用户头像图片(my-vue-project\src\assets\images\user.png) -->
<img :src="getImageUrl('user')" alt="用户头像" class="user" />
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>个人中心</el-dropdown-item>
<el-dropdown-item>退出</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown></div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
// 通过参数user的名字可以获取动态的图片的url
// 通过new URL()方法可以创建并返回一个URL对象,用来获取图片的url(百度new URL MDN)
// 通过import.meta.url可以获取当前模块的url
const getImageUrl = (user) => {
return new URL(`../assets/images/${user}.png`, import.meta.url).href
}
import { useAllDateStore } from '@/stores/index';
// 获取 store 实例
const store = useAllDateStore();
// 使用 store 中的 toggleCollapse 方法
function toggleCollapse() {
store.toggleCollapse()
}
</script>
<style lang="less" scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
background-color: #333;
}
.icons {
width: 20px;
height: 20px;
}
.l-content {
display: flex;
align-items: center;
.el-button {
margin-right: 20px;
}
}
.r-content {
.user {
width: 40px;
height: 40px;
border-radius: 50%;
}
}
:deep(.bread span) {
color: #fff !important;
cursor: pointer !important;
}
</style>
显示效果:
点击header上的四个点的menu按钮后:
完成!
附所有代码
通过百度网盘分享的文件:my-vue-project.zip
链接:https://pan.baidu.com/s/1BWVbHXtlagH3oHbrVENp1A?pwd=6666
提取码:6666