使用pinia实现菜单收缩功能(通用后台管理系统)

目录

一、Pinia的使用

(1)官网

(2)快速开始

(3)什么是store

二、前期准备

(1)组件官网(使用menu菜单)

(2)使用组件

(3)效果图

(4)实现效果

(5)Pinia

三、实战

(1)CommonAside.vue实现折叠基本

(2)CommonHeader.vue实现按钮点击后折叠


一、Pinia的使用

(1)官网

https://pinia.vuejs.org/zh/introduction.html

(2)快速开始

  • 安装
yarn add pinia
# 或者使用 npm
npm install pinia
  • 引用(main.js)
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

(3)什么是store

Store 是用 defineStore() 定义的,它的第一个参数要求是一个独一无二的名字:

import { defineStore } from 'pinia'

// 你可以任意命名 `defineStore()` 的返回值,但最好使用 store 的名字,同时以 `use` 开头且以 `Store` 结尾。
// (比如 `useUserStore`,`useCartStore`,`useProductStore`)
// 第一个参数是你的应用中 Store 的唯一 ID。
export const useAlertsStore = defineStore('alerts', {
  // 其他配置...
})

defineStore() 的第二个参数可接受两类值:Setup 函数或 Option 对象。

本文将以Setup函数作为第二个参数。

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  const doubleCount = computed(() => count.value * 2)
  function increment() {
    count.value++
  }

  return { count, doubleCount, increment }
})
  • ref() 就是 state 属性
  • computed() 就是 getters
  • function() 就是 actions

二、前期准备

(1)组件官网(使用menu菜单)

https://element-plus.org/zh-CN/component/menu.html

(2)使用组件

首先我们在src文件夹下已经创建好了components文件夹,并且创建了CommonAside.vue和CommonHeader.vue文件

//CommonAside.vue

<script setup>
import { ref ,computed} from 'vue';
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'
                }
            ]
        }
])

// 返回一个新的数组,其中包含list中所有没有children属性的元素。换句话说,这些元素没有子元素。
const noChildren = computed(() => list.value.filter(item => !item.children))
const hasChildren =computed(() => list.value.filter(item => item.children))

</script>

<template>
    <el-aside width="180px">
        <el-menu 
            text-color="#fff" 
            background-color="#545c64"
            
        >
            <h3 >通用后台管理系统</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,subIndex) 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>

<style lang="less" scoped>

.icons{
    width:18px;
    height:18px;
    margin-right:5px;
     color: #fff;
     
}
.el-menu{
    border-right:none;
    h3{
        line-height:48px;
        color:#fff;
        text-align:center;
    }
    span{
       color: #fff;
    }
   
}

.el-aside{
    
    height: 100vh;
    background-color:#545c64;
}
</style>
//CommonHeader.vue

<script setup>
import { ref ,computed} from 'vue';
const getImageUrl = (user)=>{
    return new URL(`../assets/images/${user}.png` , import.meta.url).href
    
}

</script>

<template>
   <div class="header">
        <div class="l-content">
            <el-button size="small">
                <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">
                   <!-- 动态图片 -->
                    <!-- <img src="../assets/images/${user}.png"> -->
                     <img :src="getImageUrl('user')" 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>

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

(3)效果图

(4)实现效果

我们要实现点击CommonHeader.vue文件下的按钮,实现CommonAside.vue菜单组件的折叠功能。使用menu菜单的Collapse 折叠面板就可以实现

:collapse="isCollapse"

因为涉及到两个不同组件的传值,实现数据的共享,就要使用到pinia,下面开始详细讲解本次例子如何用pinia实现菜单折叠。

(5)Pinia

 在安装和引用(main.js)Pinia后,接下来在src文件夹下创建一个stores文件夹,然后新建一个index.js文件

// 导入pinia
import { defineStore } from "pinia";
import {ref} from 'vue'
// 定义一个方法,全局暴露
function initState(){

}
export const useAllDataStore = defineStore('allData', () => {
    const state = ref(initState())
    return { 
        state,
     }
})

三、实战

(1)CommonAside.vue实现折叠基本

1.首先引用之前在stores文件夹写好的index.js

import {useAllDataStore} from '@/stores'

2.然后定义一个store, 调用useAllDataStore()

//定义一个store, 调用useAllDataStore()
const store = useAllDataStore()

3.接着对组件进行修改,对h3标签使用v-show进行显示,

  • isCollapse是true就是折叠状态,展示“后台”
  • 如果是false,就展示“通用后台管理系统”
<el-menu 
            text-color="#fff" 
            background-color="#545c64"
            :collapse="isCollapse"
>
        <!-- isCollapse是true就是折叠状态,展示后来两个字,如果是false,就展示通用后台管理系统 -->
            <h3 v-show="!isCollapse">通用后台管理系统</h3>
            <h3 v-show="isCollapse">后台</h3>

4.接着让isCollapse变成一个响应式,在stores文件夹写好的index.js补充代码,

// 导入pinia
import { defineStore } from "pinia";
import {ref} from "vue"
// 定义一个方法,全局暴露
function initState(){
    return {
        isCollapse : false
    }

}
export const useAllDataStore = defineStore('allData', () => {
    const state = ref(initState())
    return { 
        state,
     }
})

   然后回到CommonAside.vue,使用

const isCollapse = computed(()=>store.state.isCollapse)

看效果:

 isCollapse : false

 isCollapse : true

5.实现宽度变化,把宽度设置为响应式。

 <el-aside :width="width">
const width = computed(()=>store.state.isCollapse ? '64px' : '180px')

看效果:

 isCollapse : false

 isCollapse : true

最后设置 isCollapse : false,方便后续操作

(2)CommonHeader.vue实现按钮点击后折叠

(1)给按钮添加点击事件,绑定handleCollpase方法。

 <el-button size="small" @click="handleCollpase">

(2)定义该方法,实现Pinia操作

import {useAllDataStore} from '@/stores'

const store = useAllDataStore()
const handleCollpase = ()=>{
    store.state.isCollapse = !store.state.isCollapse
}

(3)看效果

发现点击该按钮,效果确实生效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值