一.引入pinia
组件间数据共享,现在要解决的是侧边栏折叠展开问题,我们要在Header组件中点击一个按钮,然后侧边栏组件就会就会进行折叠或者展开,这就涉及到组件间的传值问题,我们可以设置一个值定义是否收缩,让两个组件都共享,这样就可以实现在Header中点击,而实现的是Aside的动作。 安装pinia
npm install pinia -D
在main.js中引入pinia,并use:
import { createApp } from 'vue'
import App from './App.vue'
import "../src/assets/less/index.less"
import router from "./router"
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
**import { createPinia } from 'pinia'**
const app = createApp(App)
**const pinia = createPinia()**
app.use(ElementPlus)
app.use(router).mount('#app')
**app.use(pinia)**
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
二.实现菜单收缩功能
使用Setup Store
index.js:
另外写函数initState()是用来取代return的,return的时候不用写那么多参数了
import { defineStore } from "pinia";
import { ref } from 'vue'
function initState() { }
export const useAllDataStore = defineStore('allData', () => {
//ref 类似于state属性
//computed 类似于getter
//function 类似于actions
const state = ref(initState())
return {
state,
}
})
修改CommonAside.vue:
这里写的时候忘记写const store = useAllDataStore() 导致store没有真正在Aside中得到使用,导致出错了
<template>
<!-- 把width设置成可变的 -->
<el-aside :width="width">
<el-menu
background-color="#545c64"
text-color="#fff"
:collapse="isCollapse">
<h3 v-show="!isCollapse">内容管理平台</h3>
<h3 v-show="isCollapse">平台</h3>
<el-menu-item
v-for="item in noChildren"
:index="item.path"
:key="item.path">
<component class="icons" :is="item.icon"></component>
<span>{{ item.label }}</span>
</el-menu-item>
<!-- //有子菜单的 -->
<el-sub-menu
v-for="item in hasChildren"
:index="item.path"
:key="item.path"
>
<template #title>
<component class="icons" :is="item.icon"></component>
<span>{{ item.label }}</span>
</template>
<el-menu-item-group >
<el-menu-item
v-for="subItem in item.children"
:index="subItem.path"
:key="subItem.path"
>
<component class="icons" :is="subItem.icon"></component>
<span>{{ subItem.label }}</span>
</el-menu-item>
</el-menu-item-group>
</el-sub-menu>
</el-menu>
</el-aside>
</template>
<script setup>
import {ref,computed} from 'vue'
// 引入store
import {useAllDataStore} from '../stores'
const store = useAllDataStore()
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))
//引入store的isCollapse属性
const isCollapse=computed(()=>store.state.isCollapse)
const width=computed(()=>store.state.isCollapse ? '64px':'180px')
</script>
<style lang="less" scoped>
.icons {
width:18px;
height:18px;
}
.el-menu{
border-right:none;
h3 {
line-height: 48px;
color: #fff;
text-align: center;
}
}
.el-aside{
height:100%;
background-color: #545c64;
}
</style>
在按钮上增加 @click="handleCollapse" 事件 Header的script中增加:
和在Aside中引入和使用store的方法是一样的,也是这两句话
import { useAllDataStore } from '../stores'
const store = useAllDataStore()
<script>
import { ref } from 'vue'
**import { useAllDataStore } from '../stores'**
export default {
setup() {
** const store = useAllDataStore() **//这里Aside里面也有,就是要拿到这个方法
const user = ref('defaultUser') // 定义 user 变量
const getImageUrl = (user) => {
return new URL(`../assets/images/${user}.png`, import.meta.url).href
}
** const handleCollapse = () => {
store.state.isCollapse = !store.state.isCollapse
}**
return {
user,
getImageUrl,
** handleCollapse**
}
}
}
</script>
最后的效果: