第3天(pinia实现数据共享)

204 阅读2分钟

一.引入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)
}

二.实现菜单收缩功能

image.png

使用Setup Store

image.png 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>

最后的效果:

image.png