Skip to content

VJSP Vue3 Frame - 工具函数库使用指南

概述

VJSP Vue3 Frame项目提供了一套完整的工具函数库,位于src/utils/目录下,为项目开发提供基础工具支持。工具函数库采用模块化设计,涵盖缓存管理、安全防护、路由处理、权限控制、数据处理等核心功能。

工具函数架构

核心模块结构

项目工具函数采用分层架构设计:

src/utils/
├── 基础工具层
│   ├── index.ts          # 工具函数入口和通用工具
│   ├── cache.ts          # 缓存管理工具
│   ├── securityStorage.ts # 安全存储工具
│   └── is.ts             # 类型判断工具
├── 业务工具层
│   ├── permission.ts     # 权限控制工具
│   ├── routerHelper.ts   # 路由辅助工具
│   ├── routeUtils.ts     # 路由工具函数
│   └── messageManager.ts # 消息管理工具
└── 安全工具层
    ├── securityManager.ts # 安全管理器
    ├── rateLimit.ts       # 频率限制工具
    ├── csrfProtection.ts  # CSRF防护工具
    └── encryption.ts      # 加密工具

设计原则

  1. 单一职责原则:每个工具函数专注于特定功能
  2. 模块化设计:按功能领域划分模块,便于维护和扩展
  3. 类型安全:全面使用TypeScript确保类型安全
  4. 性能优化:内置缓存机制和性能优化策略

核心工具函数机制

1. 缓存管理机制

CacheUtil缓存工具类

机制原理

  • 支持localStorage和sessionStorage两种存储方式
  • 内置过期时间管理,自动清理过期数据
  • 支持加密存储,保护敏感数据安全
  • 提供统一的缓存操作接口

核心特性

  • 过期时间自动检测和清理
  • 存储类型自动适配
  • 加密存储支持
  • 内存缓存优化

SecurityStorage安全存储工具

机制原理

  • 基于sessionStorage的加密存储方案
  • 动态密钥生成机制,结合用户Token和浏览器指纹
  • 支持"记住我"功能,7天自动过期
  • 敏感数据自动加密存储

2. 安全防护机制

SecurityManager安全管理器

机制原理

  • 统一管理请求频率限制和CSRF防护
  • 支持全局、用户、端点三级频率限制
  • 双提交Cookie CSRF防护机制
  • 自动令牌验证和过期处理

频率限制策略

  • 全局限制:保护服务器资源,防止DDoS攻击
  • 用户限制:防止单个用户滥用API
  • 端点限制:保护敏感接口,防止暴力破解

3. 路由和权限机制

RouterHelper路由辅助工具

机制原理

  • 支持前端控制和后端控制两种路由生成模式
  • 自动扁平化多级路由结构
  • 路由缓存机制,提升性能
  • 权限过滤和路由验证

Permission权限控制工具

机制原理

  • 基于角色的权限验证体系
  • 支持严格模式和宽松模式
  • 动态权限检查和过滤
  • 组件级权限控制支持

4. 消息管理机制

MessageManager消息管理器

机制原理

  • 统一的消息提示和通知管理
  • 支持成功、警告、错误等多种消息类型
  • 消息队列管理,防止消息重叠
  • 国际化消息支持

Product模块开发示例

1. 产品数据缓存实现

typescript
// src/views/product/ProductList.vue
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { CacheUtil } from '@/utils/cache'
import { message } from '@/utils/messageManager'

// 产品列表数据
const productList = ref([])
const loading = ref(false)

// 缓存键定义
const CACHE_KEYS = {
  PRODUCT_LIST: 'product_list_cache',
  PRODUCT_DETAIL: 'product_detail_'
}

// 获取产品列表(带缓存)
const fetchProductList = async () => {
  loading.value = true

  try {
    // 检查缓存
    const cachedData = CacheUtil.getLocal(CACHE_KEYS.PRODUCT_LIST)
    if (cachedData) {
      productList.value = cachedData
      console.log('使用缓存数据')
      return
    }

    // 调用API获取数据
    const response = await productApi.getList()
    productList.value = response.data

    // 缓存数据(10分钟过期)
    CacheUtil.setLocal(CACHE_KEYS.PRODUCT_LIST, response.data, 10 * 60 * 1000)

    message.success('产品列表加载成功')
  } catch (error) {
    message.error('产品列表加载失败')
  } finally {
    loading.value = false
  }
}

// 获取产品详情(带缓存和加密)
const fetchProductDetail = async (productId: string) => {
  const cacheKey = CACHE_KEYS.PRODUCT_DETAIL + productId

  // 检查缓存
  const cachedDetail = CacheUtil.getLocal(cacheKey)
  if (cachedDetail) {
    return cachedDetail
  }

  // 调用API获取详情
  const response = await productApi.getDetail(productId)

  // 缓存敏感数据(加密存储,5分钟过期)
  CacheUtil.setEncryptedLocal(cacheKey, response.data, 5 * 60 * 1000)

  return response.data
}

// 清除产品缓存
const clearProductCache = () => {
  CacheUtil.removeLocal(CACHE_KEYS.PRODUCT_LIST)
  // 清除所有产品详情缓存
  Object.keys(localStorage)
    .filter(key => key.startsWith(CACHE_KEYS.PRODUCT_DETAIL))
    .forEach(key => CacheUtil.removeLocal(key))

  message.success('产品缓存已清除')
}

onMounted(() => {
  fetchProductList()
})
</script>

2. 产品权限控制实现

typescript
// src/views/product/components/ProductActions.vue
<script setup lang="ts">
import { hasPermission, filterByPermission } from '@/utils/permission'

// 产品操作权限定义
const PRODUCT_PERMISSIONS = {
  CREATE: 'product:create',
  EDIT: 'product:edit',
  DELETE: 'product:delete',
  VIEW: 'product:view'
}

// 检查当前用户权限
const canCreateProduct = hasPermission(PRODUCT_PERMISSIONS.CREATE)
const canEditProduct = hasPermission(PRODUCT_PERMISSIONS.EDIT)
const canDeleteProduct = hasPermission(PRODUCT_PERMISSIONS.DELETE)

// 产品操作按钮配置
const actionButtons = [
  {
    label: '创建产品',
    icon: 'plus',
    permission: PRODUCT_PERMISSIONS.CREATE,
    handler: () => createProduct()
  },
  {
    label: '编辑产品',
    icon: 'edit',
    permission: PRODUCT_PERMISSIONS.EDIT,
    handler: () => editProduct()
  },
  {
    label: '删除产品',
    icon: 'delete',
    permission: PRODUCT_PERMISSIONS.DELETE,
    handler: () => deleteProduct()
  }
]

// 根据权限过滤操作按钮
const visibleButtons = filterByPermission(actionButtons, 'permission')

// 产品操作函数
const createProduct = () => {
  if (!hasPermission(PRODUCT_PERMISSIONS.CREATE)) {
    message.warning('没有创建产品的权限')
    return
  }
  // 创建产品逻辑
}

const editProduct = () => {
  if (!hasPermission(PRODUCT_PERMISSIONS.EDIT)) {
    message.warning('没有编辑产品的权限')
    return
  }
  // 编辑产品逻辑
}

const deleteProduct = () => {
  if (!hasPermission(PRODUCT_PERMISSIONS.DELETE)) {
    message.warning('没有删除产品的权限')
    return
  }
  // 删除产品逻辑
}
</script>

<template>
  <div class="product-actions">
    <el-button
      v-for="button in visibleButtons"
      :key="button.label"
      :icon="button.icon"
      @click="button.handler"
    >
      {{ button.label }}
    </el-button>
  </div>
</template>

3. 产品路由配置和缓存

typescript
// src/router/modules/product.ts
import { Layout } from '@/utils/routerHelper'
import type { AppRouteRecordRaw } from '@/types/router'

const ProductRoute: AppRouteRecordRaw = {
  path: '/product',
  component: Layout,
  redirect: '/product/list',
  name: 'Product',
  meta: {
    title: '产品管理',
    icon: 'shopping',
    permission: 'product',
    keepAliveName: 'ProductLayout',
  },
  children: [
    {
      path: 'list',
      component: () => import('@/views/product/ProductList.vue'),
      name: 'ProductList',
      meta: {
        title: '产品列表',
        icon: 'list',
        permission: 'product:view',
        keepAliveName: 'ProductList',
        noCache: false, // 启用缓存
      },
    },
    {
      path: 'detail/:id',
      component: () => import('@/views/product/ProductDetail.vue'),
      name: 'ProductDetail',
      meta: {
        title: '产品详情',
        icon: 'detail',
        permission: 'product:view',
        keepAliveName: 'ProductDetail',
        noCache: true, // 禁用缓存(详情页通常不需要缓存)
      },
      props: true,
    },
    {
      path: 'create',
      component: () => import('@/views/product/ProductCreate.vue'),
      name: 'ProductCreate',
      meta: {
        title: '创建产品',
        icon: 'plus',
        permission: 'product:create',
        noCache: true, // 创建页面不需要缓存
      },
    },
  ],
}

export default ProductRoute

4. 产品API安全防护

typescript
// src/api/product.ts
import { securityManager } from '@/utils/securityManager'
import { message } from '@/utils/messageManager'

class ProductApi {
  private baseURL = '/api/product'

  // 获取产品列表(带频率限制)
  async getList(params?: any) {
    // 检查频率限制
    const userId = this.getCurrentUserId()
    const endpoint = `${this.baseURL}/list`

    if (!securityManager.isRequestAllowed(userId, endpoint)) {
      message.warning('请求过于频繁,请稍后再试')
      throw new Error('Rate limit exceeded')
    }

    // 添加CSRF防护头
    const headers = securityManager.getCSRFHeaders('GET')

    return await axios.get(endpoint, {
      params,
      headers,
    })
  }

  // 创建产品(带安全验证)
  async create(productData: any) {
    const userId = this.getCurrentUserId()
    const endpoint = `${this.baseURL}/create`

    // 检查频率限制
    if (!securityManager.isRequestAllowed(userId, endpoint)) {
      message.warning('操作过于频繁,请稍后再试')
      throw new Error('Rate limit exceeded')
    }

    // 添加CSRF防护头
    const headers = securityManager.getCSRFHeaders('POST')

    return await axios.post(endpoint, productData, { headers })
  }

  // 删除产品(带权限验证)
  async delete(productId: string) {
    const userId = this.getCurrentUserId()
    const endpoint = `${this.baseURL}/delete/${productId}`

    // 检查频率限制
    if (!securityManager.isRequestAllowed(userId, endpoint)) {
      message.warning('操作过于频繁,请稍后再试')
      throw new Error('Rate limit exceeded')
    }

    // 添加CSRF防护头
    const headers = securityManager.getCSRFHeaders('DELETE')

    return await axios.delete(endpoint, { headers })
  }

  private getCurrentUserId(): string {
    // 获取当前用户ID的逻辑
    const userStore = useUserStore()
    return userStore.getUserInfo?.id || 'anonymous'
  }
}

export const productApi = new ProductApi()

性能优化实践

1. 缓存策略优化

产品列表缓存优化

  • 使用内存缓存+持久化缓存双重机制
  • 根据数据更新频率设置合理的过期时间
  • 实现缓存预热机制,提升用户体验

2. 组件缓存配置

keep-alive缓存策略

vue
<!-- src/layout/components/AppMain.vue -->
<template>
  <section class="app-main">
    <router-view v-slot="{ Component }">
      <transition name="fade-transform" mode="out-in">
        <keep-alive :include="cachedViews">
          <component :is="Component" :key="route.path" />
        </keep-alive>
      </transition>
    </router-view>
  </section>
</template>

<script setup lang="ts">
import { useTagsViewStore } from '@/layout/stores/tagsView'

const route = useRoute()
const tagsViewStore = useTagsViewStore()

// 获取缓存视图列表
const cachedViews = computed(() => tagsViewStore.getCachedViews)
</script>

3. 请求优化策略

产品API请求优化

  • 实现请求去重,避免重复请求
  • 使用请求缓存,减少服务器压力
  • 实现请求优先级管理,重要请求优先处理

最佳实践指南

1. 工具函数使用规范

导入规范

typescript
// 推荐:按需导入
import { CacheUtil } from '@/utils/cache'
import { hasPermission } from '@/utils/permission'

// 不推荐:全局导入(增加打包体积)
import * as utils from '@/utils'

错误处理规范

typescript
// 使用try-catch处理工具函数异常
try {
  const userInfo = SecurityStorage.getUserInfo()
} catch (error) {
  console.error('获取用户信息失败:', error)
  // 降级处理或用户提示
}

2. 缓存使用建议

适合缓存的数据

  • 静态配置数据
  • 用户基本信息
  • 产品分类数据
  • 权限菜单数据

不适合缓存的数据

  • 实时性要求高的数据
  • 频繁更新的业务数据
  • 敏感的交易数据

3. 安全防护配置

生产环境配置

typescript
// 启用严格的安全防护
const securityConfig = {
  rateLimit: {
    enabled: true,
    global: { maxRequests: 100, timeWindow: 60000 },
    user: { maxRequests: 10, timeWindow: 60000 },
    endpoint: { maxRequests: 5, timeWindow: 60000 },
  },
  csrf: {
    enabled: true,
    tokenExpiry: 30 * 60 * 1000, // 30分钟
    doubleSubmit: true,
  },
}

总结

VJSP Vue3 Frame的工具函数库为项目开发提供了强大的基础支持。通过合理的模块划分、完善的机制设计和性能优化策略,工具函数库能够有效提升开发效率和代码质量。在实际开发中,建议根据具体业务需求选择合适的工具函数,并遵循最佳实践规范。