【vue】适合大型项目的封装(接口,全局字典,表格表头)

目录

一、接口封装(完整分层实现)

1. 核心请求层封装 (src/api/core/http.js)

2. 业务模块API (src/api/modules/user.api.js)

二、全局字典管理(完整实现)

1. Vuex Store 封装 (src/store/modules/dict.js)

2. 字典混入方法 (src/mixins/dict.js)

3. 在组件中使用

三、通用表格组件(完整实现)

1. 组件实现 (src/components/CommonTable/index.vue)

2. 渲染函数组件 (src/components/CommonTable/RenderCell.vue)

3. 使用示例

四、关键设计说明

五、扩展建议


一、接口封装(完整分层实现)

1. 核心请求层封装 (src/api/core/http.js)
import axios from 'axios'
import { Message } from 'element-ui' // 以ElementUI为例

class HttpCore {
  constructor(config) {
    // 创建axios实例
    this.instance = axios.create({
      baseURL: config.baseURL,
      timeout: config.timeout || 15000,
      headers: config.headers || {}
    })

    // 安装拦截器
    this.setupInterceptors()
  }

  setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(config => {
      // 自动携带token
      const token = localStorage.getItem('token')
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }
      return config
    }, error => {
      return Promise.reject(error)
    })

    // 响应拦截器
    this.instance.interceptors.response.use(
      response => {
        // 处理标准响应结构
        if (response.data.code === 200) {
          return response.data.data
        }
        // 处理业务错误
        Message.error(response.data.message || '请求失败')
        return Promise.reject(response.data)
      },
      error => {
        // 处理HTTP错误
        const status = error.response?.status
        let message = '请求异常'
        
        switch (status) {
          case 401:
            message = '登录已过期,请重新登录'
            localStorage.removeItem('token')
            router.push('/login')
            break
          case 403:
            message = '没有操作权限'
            break
          case 500:
            message = '服务器内部错误'
            break
        }
        
        Message.error(message)
        return Promise.reject(error)
      }
    )
  }

  // 封装请求方法
  get(url, params, config = {}) {
    return this.instance.get(url, { params, ...config })
  }

  post(url, data, config = {}) {
    return this.instance.post(url, data, config)
  }

  put(url, data, config = {}) {
    return this.instance.put(url, data, config)
  }

  delete(url, config = {}) {
    return this.instance.delete(url, config)
  }
}

// 创建全局实例
const http = new HttpCore({
  baseURL: process.env.VUE_APP_BASE_API,
  timeout: 20000
})

export default http
2. 业务模块API (src/api/modules/user.api.js)

import http from '../core/http'

export default {
  /**
   * 获取用户列表
   * @param {Object} params - 查询参数
   * @returns {Promise} 
   */
  getUserList(params = { page: 1, size: 10 }) {
    return http.get('/user/list', params)
  },

  /**
   * 创建用户
   * @param {Object} userData - 用户数据
   * @returns {Promise}
   */
  createUser(userData) {
    return http.post('/user/create', userData)
  },

  /**
   * 更新用户状态
   * @param {Number} userId - 用户ID
   * @param {Number} status - 新状态
   * @returns {Promise}
   */
  updateUserStatus(userId, status) {
    return http.put(`/user/${userId}/status`, { status })
  }
}

3. 统一出口文件 (src/api/index.js)

import userApi from './modules/user.api'
import productApi from './modules/product.api'

export default {
  user: userApi,
  product: productApi
}

二、全局字典管理(完整实现)

1. Vuex Store 封装 (src/store/modules/dict.js)

const state = {
  dictCache: {} // 字典缓存 { dictKey: [] }
}

const mutations = {
  SET_DICT_DATA: (state, { key, data }) => {
    state.dictCache[key] = data
  }
}

const actions = {
  // 加载字典数据
  async loadDict({ commit }, dictKeys) {
    const unloadedKeys = dictKeys.filter(key => !state.dictCache[key])
    
    if (unloadedKeys.length === 0) return
    
    try {
      // 假设后端接口为 POST /api/dict/list 接收keys数组
      const res = await http.post('/dict/list', { keys: unloadedKeys })
      
      Object.entries(res.data).forEach(([key, items]) => {
        commit('SET_DICT_DATA', {
          key,
          data: items.map(item => ({
            value: item.dictValue,
            label: item.dictLabel,
            color: item.color // 扩展字段示例
          }))
        })
      })
    } catch (err) {
      console.error('字典加载失败:', err)
    }
  }
}

const getters = {
  getDict: state => key => state.dictCache[key] || []
}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}
2. 字典混入方法 (src/mixins/dict.js)

export default {
  methods: {
    /**
     * 初始化字典(自动处理加载和监听)
     * @param {Array|String} dictKeys - 字典键
     */
    initDict(dictKeys) {
      const keys = Array.isArray(dictKeys) ? dictKeys : [dictKeys]
      
      // 触发字典加载
      this.$store.dispatch('dict/loadDict', keys)
      
      // 返回计算属性
      return keys.reduce((computedDict, key) => {
        computedDict[key] = () => this.$store.getters['dict/getDict'](key)
        return computedDict
      }, {})
    },
    
    /**
     * 字典格式化显示
     * @param {*} value - 原始值
     * @param {String} dictKey - 字典键
     * @returns {String} 格式化后的显示值
     */
    dictFormat(value, dictKey) {
      const dict = this.$store.getters['dict/getDict'](dictKey)
      const item = dict.find(d => d.value === value)
      return item ? item.label : '--'
    }
  }
}
3. 在组件中使用



三、通用表格组件(完整实现)

1. 组件实现 (src/components/CommonTable/index.vue)




2. 渲染函数组件 (src/components/CommonTable/RenderCell.vue)
 
  
3. 使用示例



四、关键设计说明

  1. 接口层设计亮点

    • 错误统一处理:拦截器中统一处理401等常见状态码

    • 业务代码隔离:每个业务模块独立文件,避免耦合

    • 自动重试机制:可扩展添加axios-retry插件实现

  2. 字典系统优势

    • 按需加载:只在首次使用时请求字典数据

    • 自动更新:当字典数据变化时,所有使用位置自动更新

    • 样式扩展:支持通过字典返回颜色等样式信息

  3. 表格组件特性

    • 配置驱动:通过columns配置实现不同展示需求

    • 渲染扩展:支持JSX/render函数实现复杂交互

    • 分页集成:内置标准化分页逻辑

    • 排序支持:自动处理排序参数传递

  4. 性能优化措施

    • 防抖加载:可在dataLoader中添加防抖逻辑

    • 缓存策略:接口层可添加LRU缓存机制

    • 虚拟滚动:对大数据量表格可集成虚拟滚动

五、扩展建议

  1. 增加表格工具栏

  2. 实现批量操作

    // 在CommonTable中添加
    props: {
      selection: { type: Boolean, default: false }
    },
    
    methods: {
      handleSelectionChange(selection) {
        this.$emit('selection-change', selection)
      }
    }
  3. 添加导出功能

    // 在CommonTable中添加
    methods: {
      exportData() {
        const headers = this.processedColumns
          .filter(col => !col.hidden)
          .map(col => ({
            label: col.label,
            prop: col.prop
          }))
        
        exportExcel({
          headers,
          data: this.tableData,
          filename: '导出数据'
        })
      }
    }

这套封装方案经过多个中后台项目验证,可满足以下需求场景:

快速搭建CRUD界面

统一处理权限控制

实现复杂表格交互

保持多模块样式统一

快速响应业务需求变化

码字不易,各位大佬点点赞呗

你可能感兴趣的:(VUE,vue.js,前端,javascript)