了解 pinia
Pinia类似于vuex,是Vue的状态存储库,它允许您跨组件/页面共享状态。
pinia 的优点
- 相对于
vuex来说,它支持创建多个store对象互不影响。例如 侧边栏导航、用户相关信息可以创建两个相对应的store存储对应的信息,实现信息的互不干扰,更易于维护。 - 相对于
vuex来说,它去掉了mutations这个冗余的模块,它只包含state,getters,actions三个概念。
pinia 使用
安装
yarn add pinia
# 或者使用 npm
npm install pinia
使用
这里以侧边导航为例,实现导航的效果如下
- 封装导航组件
<template>
<!-- 动态路由 -->
<!-- :popper-append-to-body="false" -->
<el-menu :backgroundColor="_navBackgroudColor" :text-color="_navTextColor" :active-text-color="_activeTextColor"
:collapse="_isCollapse" :default-openeds="_defaultOpeneds" :unique-opened="true">
<el-sub-menu :index="item.id" v-for="item in menuLists" :key="JSON.stringify(item)">
<template #title>
<el-icon><i :class="item.icon"></i></el-icon>
<span>{{ item.authName }}</span>
</template>
<el-menu-item :index="'/' + subItem.path" @click="goPath(subItem)" v-for="subItem in item.children"
:key="subItem.index">
<template #title>
<el-icon><i :class="subItem.icon"></i></el-icon>
<span>{{ subItem.authName }}</span>
</template>
</el-menu-item>
</el-sub-menu>
</el-menu>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia';
import { useMenuStore } from '@/store/menu.ts';
import { useRouter } from "vue-router";
const menuStore = useMenuStore();
const router = useRouter();
const { menuLists, _navBackgroudColor, _navTextColor, _isCollapse, _activeTextColor, _defaultOpeneds } = storeToRefs(menuStore);
const goPath = (item: { path: string }) => {
console.log(item)
router.push({
path: item.path
})
}
</script>
- @/store/menu.ts
import { defineStore } from "pinia";
/**
* navBackgroudColor 导航栏的背景色
* navTextColor 导航栏字体颜色
* isCollapse 是否展开导航栏
* activeTextColor 激活字体颜色
* defaultOpeneds 默认打开项
* **/
interface BasicState {
menuList: any[];
navBackgroudColor: string;
navTextColor: string;
isCollapse: boolean;
activeTextColor: string;
defaultOpeneds: string | number[];
}
export const useMenuStore = defineStore("menuList", {
state: (): BasicState => ({
menuList: [],
navBackgroudColor: "#22239b",
isCollapse: false,
navTextColor: "#f5f5f5",
activeTextColor: "#ffd04b",
defaultOpeneds: [21],
}),
getters: {
menuLists: (state) => state.menuList,
_navBackgroudColor: (state) => state.navBackgroudColor,
_isCollapse: (state) => state.isCollapse,
_navTextColor: (state) => state.navTextColor,
_activeTextColor: (state) => state.activeTextColor,
_defaultOpeneds: (state) => state.defaultOpeneds,
},
actions: {
setMenuList(list: any[]) {
this.menuList = list;
},
setNavBackgroudColor(navBackgroudColor: string) {
this.navBackgroudColor = navBackgroudColor;
},
setIsCollapse(isCollapse: boolean) {
this.isCollapse = isCollapse;
},
setNavTextColor(navTextColor: string) {
this.navTextColor = navTextColor;
},
setActiveTextColor(activeTextColor: string) {
this.activeTextColor = activeTextColor;
},
setDefaultOpeneds(defaultOpeneds: string | number[]) {
this.defaultOpeneds = defaultOpeneds;
},
reset() {
this.menuList = [];
this.navBackgroudColor = "#141414";
this.isCollapse = true;
this.navTextColor = "#f5f5f5";
this.activeTextColor = "#fff";
this.defaultOpeneds = [1];
},
},
});
- APP.vue中获取菜单列表数据
<script setup lang="ts">
import { onMounted } from 'vue';
import { getMenuList } from '@/utils/api/menu.ts'
import { useMenuStore } from '@/store/menu.ts';
const menuStore = useMenuStore();
// 获取菜单
const getMenuListFun = async (user: object) => {
const data = await getMenuList(user)
console.log('权限列表', data);
menuStore.setMenuList(data.data.menuList.admin)
}
// 进入页面初始化
onMounted(() => {
getMenuListFun({
userId: 1
});
})
</script>
- 返回数据结果(Mock模拟)
const roles = {
admin: [
{
id: 1,
authName: "统计分析",
icon: "iconfont icon-shuzhuangtu",
children: [
{
id: 11,
authName: "案件分析",
icon: "iconfont icon-baobiao",
path: "/index",
rights: ["view", "edit", "add", "delete"],
},
{
id: 12,
authName: "仲裁员分析",
icon: "iconfont icon-tongji2",
path: "appraiserLibrary",
rights: ["view", "edit", "add", "delete"],
},
],
},
{
id: 2,
authName: "案件管理",
icon: "iconfont icon-bujianshenqingdan",
children: [
{
id: 21,
authName: "案件查询",
icon: "iconfont icon-wj-jdws",
path: "ProjectRegistration",
rights: ["view", "edit", "add", "delete"],
},
{
id: 22,
authName: "案件录入",
icon: "iconfont icon-chakan",
path: "ProjectQuery",
rights: ["view", "edit", "add", "delete"],
},
],
},
],
};
const data = {
code: 200,
msg: "请求成功!",
data: {
menuList: roles,
},
};
export default data;