setup语法糖中使用pinia

501 阅读1分钟

了解 pinia

Pinia 类似于vuex,是 Vue 的状态存储库,它允许您跨组件/页面共享状态。

pinia 的优点

  • 相对于vuex来说,它支持创建多个store对象互不影响。例如 侧边栏导航、用户相关信息可以创建两个相对应的store存储对应的信息,实现信息的互不干扰,更易于维护。
  • 相对于vuex来说,它去掉了mutations这个冗余的模块,它只包含 stategettersactions三个概念。

pinia 使用

安装

    yarn add pinia
    # 或者使用 npm
    npm install pinia

使用

这里以侧边导航为例,实现导航的效果如下

image.png image.png

  • 封装导航组件
<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;