一起来手撸一个管理后台vite+vue3--实战篇

536 阅读5分钟

前言

在之前的文章中已经把项目的基础架构搭建好了,也把登录功能和权限问题完成了。现在则要进入实战环节了.本文主要介绍后台管理的实际项目中一些常用插件的使用方法、常用配置、实际遇到的一些问题。

UI框架 Element-Plus

  • 安装

    yarn add element-plus
    
  • 完整引用

    // main.js 
    import { createApp } from 'vue'
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    import locale from 'element-plus/lib/locale/lang/zh-cn'; //全局配置国际化的配置
    const app = createApp(App)
    app.use(ElementPlus, { locale }) // 挂载
    app.mount('#app')
    
  • 按需引用

    如果对于打包后的体积有要求的话可以使用按需加载

    // 安装辅助的插件
    yarn add -D unplugin-vue-components unplugin-auto-import
    
    //  vite.config.js 配置
    import AutoImport from 'unplugin-auto-import/vite'
    import Components from 'unplugin-vue-components/vite'
    import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
    export default {
      plugins: [
        // ...other option
        AutoImport({
          resolvers: [ElementPlusResolver()],
        }),
        Components({
          resolvers: [ElementPlusResolver()],
        }),
      ],
    }
    

    使用按需加载的话需要注意事项

    1. 在按需加载的时候使用组件API的话,需要手动加载样式
      import 'element-plus/es/components/message/style/css'
      import { ElMessageBox } from 'element-plus';
      
      可以在main.js统一加载,注意需要放在App引用之前,否则会样式错乱
      import { createApp } from 'vue';
      import 'element-plus/es/components/message-box/style/css'
      import 'element-plus/es/components/message/style/css'
      import App from './App.vue';
      //...other
      
    2. 国际化的时候需要使用组件el-config-provider包裹视图
      // App.vue
      <template>
          <el-config-provider :locale="zhCn">
              <router-view />
          </el-config-provider>
      </template>
      <script setup>
      import zhCn from 'element-plus/lib/locale/lang/zh-cn'
      //...
      </script>
      

VueRouter

路由的相关配置可以看上一篇文章 一起来手撸一个管理后台vite+vue3--权限控制

Pinia 状态管理

Pinia 是 Vue 新一代的状态管理器

  • 安装
    yarn add element-plus
    
  • 配置
    // src/store/Public.js
    import { defineStore } from 'pinia'
    export const PublicStore = defineStore('Public', { // Public 在整个项目中需要唯一
        state: () => {
            return { userMsg: {} }
        },
        getters: {
            getUserMsg: (state) => {
                return state.userMsg
            }
        },
        actions: {
            setUserMsg(userMsg) {
                this.userMsg = userMsg
            }
        }
    })
    
  • 使用
    // mian.js 挂载
    import { createPinia } from 'pinia'
    app.use(createPinia())
    
    // src/views/public/home.vue
    // 获取数据 在需要使用的的地方直接引用
    import { PublicStore } from '@/store/Public'
    const store = PublicStore()
    console.log(store.userMsg)
    // 也可以解构 store获取数据
    const { userMsg, getUserMsg } = { ...store }
    // 设置新的数据
    store.setUserMsg({
        userName: 'newName',
        token: 34523462456342563456,
    })
    
    pinia使用注意事项
    • store的定义需要唯一
      defineStore('Public', {}) // Public 在整个项目中需要唯一
      
    • 解构获取store的情况下 解构的结果是非响应式的,需要使用pinia提供的函数storeToRefs 进行解构
      import { PublicStore } from '@/store/Public'
      import { storeToRefs } from 'pinia'
      const store = PublicStore()
      const { userMsg, getUserMsg } = { ...store } // 非响应式
      const { userMsg, getUserMsg } = storeToRefs(store) // 响应式
      

Echart 图表

  • 安装

    yarn add echarts
    
  • 使用

    Echart提供了全局安装和按需引用

    // src/util/echart.js
    // 全局引用
        import * as echarts from 'echarts';
    // 按需引用
        // 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
        import * as echarts from 'echarts/core';
        // 引入柱状图,折线图图表,图表后缀都为 Chart
        import { BarChart, LineChart } from 'echarts/charts';
        // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
        import { TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent } from 'echarts/components';
        // 标签自动布局,全局过渡动画等特性
        import { LabelLayout, UniversalTransition } from 'echarts/features';
        // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
        import { CanvasRenderer } from 'echarts/renderers';
        // 注册必须的组件
        echarts.use([TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, BarChart, LineChart, LabelLayout, UniversalTransition, CanvasRenderer]);
        export default echarts
    

    渲染图表。下面只是一个最基础的例子,更多的配置和示例请看官网

    import echart from '@/util/echart'
    import { onMounted } from 'vue';
    import { ref } from 'vue'
    let dataView = ref(null);
    onMounted(() => {
        let myChart = echart.init(dataView.value);
        let option = {
            xAxis: {
                type: 'category',
                data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
            },
            yAxis: {
                type: 'value'
            },
            series: [
                {
                    data: [150, 230, 224, 218, 135, 147, 260],
                    type: 'line'
                }
            ]
        };     
        myChart.setOption(option);
    })
    

    Tips: 在Vue3的 VNode 上使用ref。只需在DOM上定义一个ref <div ref="dataView"></div> 然后在<script>中定义一个同名的变量let dataView = ref(null);则 VNode 的相应元素或组件实例将被分配给该 ref 的值

tinymce 富文本

  • 安装

    yarn add @tinymce/tinymce-vue
    
  • 使用

    <template>
        <div>
            <Editor v-model="content" api-key="0mfe3zktpeq7p77e1lprk9aust6b2n4lyvdyqfljwy05iozi" :init="init" />
            <el-button @click="save()" class="self-btn-28" type="primary">保存</el-button>
        </div>
    </template>
    <script setup>
        import Editor from '@tinymce/tinymce-vue'
        import { onMounted, ref } from 'vue';
        let content = ref('')
        let init = ref({
            width: 900,
            height: 500,
            language: 'zh_CN', // 语言包
            images_upload_handler: (e) => setupEdit(e), // 上传图片自定义函数
            plugins: 'preview autosave save image link media table nonbreaking lists wordcount help quickbars emoticons'
        })
        const save = () => {
            console.log('编辑内容:' + content.value);
        }
        const setupEdit = (v) => {
            console.log('图片名称:' + v.filename());
        }
    </script>
    

    Tips: api-key在官网注册后获得官方文档

项目打包压缩

项目文件压缩

不想打包进库的依赖,在index.html引用对应库的CDN。

  • vue示例
    //index.html 添加
    <script src="https://unpkg.com/vue@next"></script>
    
    //vite.config.js
    export default defineConfig({
        // other option
        build: {
            rollupOptions: {
                // 确保外部化处理那些你不想打包进库的依赖
                external: ['vue'],
                output: {
                    // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
                    globals: {
                        vue: 'Vue'
                    }
                }
            }
        }
    })
    
    原始包大小2.40M,配置后的构建包大小变为了2.32M缩小了0.08M
  • element-plus
     //index.html 添加 添加elememt的CDN
     <link rel="stylesheet" href="//unpkg.com/element-plus/dist/index.css" />
     <script src="https://unpkg.com/vue@next"></script>
     <script src="https://unpkg.com/element-plus"></script>
     
     //vite.config.js 
     - import AutoImport from 'unplugin-auto-import/vite' // 删除elememt按需加载
     - import Components from 'unplugin-vue-components/vite' // 删除elememt按需加载
     - import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' // 删除elememt按需加载
     export default defineConfig({
         // other option
         plugins: [
             //...
            -  AutoImport({  // 删除elememt按需加载
            -      resolvers: [ElementPlusResolver()],
            -  }),
            -  Components({  // 删除elememt按需加载
            -      resolvers: [ElementPlusResolver()],
            -  }),
         ],
         build: {
             rollupOptions: {
                 external: ['vue', 'element-plus'], // 添加elememt
                 output: {
                     globals: {
                         vue: 'Vue',
                         'element-plus': 'element-plus', // 添加elememt
                     }
                 }
             }
         }
     })
     
     // mian.js 全局加载elememt
     import ElementPlus from 'element-plus'
     app.use(ElementPlus)
    
    原始包大小2.32M,配置后的构建包大小变为了1.98M缩小了0.3M。 其他的库类似

图片压缩

  • 安装插件
     yarn add vite-plugin-imagemin -D
    
  • 配置
    // vite.config.js
    import { defineConfig } from 'vite'
    import viteImagemin from 'vite-plugin-imagemin'
    export default defineConfig({
        plugins: [
            viteImagemin({
                gifsicle: {
                    optimizationLevel: 7,
                    interlaced: false,
                },
                optipng: {
                    optimizationLevel: 7,
                },
                mozjpeg: {
                    quality: 20,
                },
                pngquant: {
                    quality: [0.8, 0.9],
                    speed: 4,
                },
                svgo: {
                    plugins: [
                        {
                            name: 'removeViewBox',
                        },
                        {
                            name: 'removeEmptyAttrs',
                            active: false,
                        },
                    ],
                },
            }),
        ],
    })
    

下面是我打包后的压缩结果,压缩效果还是挺明显的。 image.png

Tips:在安装插件的时候可能会出现安装失败的情况。出现这种情况的话貌似是vite-plugin-imagemin插件的依赖安装不起来。所以我们手动安装插件需要的依赖,然后在安装插件。这里显示gifsicle安装不成功,手动安装yarn add gifsicle -D image.png

git提交规范

请看另一篇文章 项目规范一-git commit 配置

最后

完整代码戳这里 vueAdmin