vue项目 优化

48 阅读3分钟
  1. 构建优化

    • 使用 UglifyJsPlugin 进行代码压缩,删除注释和 console.log 语句
    • 配置了文件名哈希,有利于缓存控制(filename: 'js/[name].[hash:8].js', chunkFilename: 'js/[name].[chunkhash:8].js')
    • 设置了路径别名(alias),简化导入路径
config.resolve.alias
            .set('@', resolve('src'))
            .set('services', resolve('src/services'))
            .set('commonStyle', resolve('src/commonStyle'))
            .set('views', resolve('src/views'))
            .set('Api', resolve('src/api'))
            .set('images', resolve('src/images'))
// vue.config.js
module.exports = {
    // ...
    configureWebpack: {
        output:{
            filename: 'js/[name].[hash:8].js',
            chunkFilename: 'js/[name].[chunkhash:8].js'
        },
        optimization: {
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        // 删除注释
                        output: {
                            comments: false
                        },
                        // 删除console debugger 删除警告
                        compress: {
                            drop_console: true,//console
                            drop_debugger: false,
                            pure_funcs: ['console.log']//移除console
                        }
                    }
                })
            ]
        },
        // ...
    }
}
  1. 路由懒加载

    • 所有路由组件都使用动态导入(如 const Organization = () => import("@/views/ProcessManagement/Organization/Index.vue")),实现了按需加载
    • 这减少了初始加载时间,只有访问特定路由时才会加载相应组件
// src/router/index.ts
const Organization = () => import("@/views/ProcessManagement/Organization/Index.vue")
const OrgDetail = () => import("@/views/ProcessManagement/Organization/Detail.vue")
const Project = () => import("@/views/ProcessManagement/Project/Index.vue")
// ... 其他懒加载组件

export const routes: Array<RouteRecordRaw> = [
  {
    path: "/process_management",
    name: "process_management",
    redirect: "/process_management/organization",
    meta: { title: "审核管理" },
    component: Layout,
    children: [
      {
        path: "organization",
        name: 'organization',
        meta: { title: "机构审核" },
        component: Organization,
      },
      // ... 其他路由配置
    ]
  },
  // ... 其他路由组
]
  1. 状态管理优化

    • 使用 Pinia 替代 Vuex,Pinia 提供更好的 TypeScript 支持和更简洁的 API
    • 状态分离管理,如 Organization.ts 中对不同模块状态的管理
// src/api/proManagement/Organization.ts
import { defineStore } from "pinia";
import { reactive } from "vue";

export const useStore = defineStore("review", () => {
    const organ = reactive({
        pageNum: 1,
        search: ""
    })

    const project = reactive({
        pageNum: 1,
        search: ""
    })

    // ... 其他状态和方法

    return {
        organ,
        project,
        proEvolve,
        report,
        modifyOrganPageNum,
        modifyOrganSearch,
        // ... 其他返回值
    }
})
  1. API 请求优化

    • 封装了统一的请求处理(Get, Post, DownLoad 方法)
    • 实现了请求拦截器,统一处理错误和认证问题
    • 使用 axios 进行 HTTP 请求管理
// src/api/Request.ts
import axios from 'axios'
// ... 其他导入

// 跨域携带cookie 
// 防止发送options请求
axios.defaults.headers.post['Content-Type'] = 'application/json';

// 配置响应拦截器
axios.interceptors.response.use(function (response) {
    // 正常响应处理
    return response
  }, function (error) {
    if (error.response.status === 401) {
        // redirectToLogin()
    }
    return Promise.reject(error)
  })

export function Get(path, params?) {
    if (typeof params !== "object") params = {};
    return axios.get(`${HOST}${path}`, { 
        params,
        headers: {
            Authorization: tokenValue
        }
    }).then(res => {
        if (!res.data.isSuccess) {
            delError(res.data.resultCode, res.data.resultMsg)
        }
        return res.data
    })
}

export function Post(path, data = {}) {
    // ... Post 方法实现
}
  1. 组件优化

    • 使用 setup 语法糖简化组件代码
    • 使用 reactive 和 ref 进行响应式数据管理
    • 条件渲染(v-if)减少不必要的 DOM 元素
<!-- src/views/ProcessManagement/AnnualReport/Index.vue -->
<script setup>
import { defineComponent, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter, useRoute } from "vue-router";
import { annualColumns } from '../common/listArray.ts'
import { ProjectEvoType } from '@/common/enum'
import { getAnnualReportList, annualReportCheck } from "@/services/proManagement";
import { useStore } from '@/api/proManagement/Organization';
import { storeToRefs } from 'pinia';

// 使用 setup 语法糖简化组件代码
const store = useStore();
const router = useRouter();
const { report } = storeToRefs(store);

// 使用 reactive 和 ref 进行响应式数据管理
const total = ref(0)
const datas = ref([])
const params = reactive({
    status: status || report.value.search,
    pageNum: +report.value.pageNum || 1,
    pageSize: 10,
})

// 条件渲染减少不必要的 DOM 元素
const fetch = async() => {
    // ... 数据获取逻辑
}
</script>
<template>
    <!-- 条件渲染示例 -->
    <el-button
        v-if="(scope.row.subStatus == 3)"
        @click="doClick(2, scope)"
        type="danger"
        class="pd_0"
        text
    >审批</el-button>
</template>
  1. 工具函数优化

    • 使用 Promise 处理异步操作,如图片加载
    • 封装了常用功能,如 ScrollToTop 等
// src/common/utils.ts
export function GetImageSize(file: File): Promise<{ width: number, height: number }> {
    return new Promise((reslove, reject) => {
        const reader = new FileReader();
        reader.onload = (e: ProgressEvent<FileReader>) => {
            const data = e.target?.result?.toString();
            //加载图片获取图片真实宽度和高度
            const image = new Image();
            image.onload = function () {
                const width = image.width;
                const height = image.height;
                reslove({ width: width, height: height });
            };
            image.onerror = function (err) {
                reject(err)
            }
            image.src = data || "";
        }
        reader.readAsDataURL(file);
    });
}

export function ScrollToTop(): void {
    const main = document.querySelector('.el-main');
    if (main) { main.scrollTo(0, 0); }
}
  1. 性能优化

    • 分页加载数据,减少一次性加载的数据量
    • 使用 Element Plus 组件库,减少自定义组件开发成本
<!-- 分页加载数据示例 -->
<el-pagination
    v-model:current-page="params.pageNum"
    @size-change="handleSizeChange"
    @current-change="handlePageChange"
    :page-size="params.pageSize"
    :total="total"
    layout="prev,pager,next,sizes,total,jumper"
>
</el-pagination>

<script setup>
// 分页处理函数
const handleSizeChange = (val) => {
    params.pageNum = 1
    params.pageSize = val
    fetch()
}

const handlePageChange = (val) => {
    params.pageNum = val;
    modifyReportNum(val);
    fetch()
}
</script>

这些优化措施共同提高了应用的加载速度、运行效率和用户体验,同时也提升了代码的可维护性和开发效率。