基于后端項目的前端開發實踐記錄
📋 項目概述
項目名稱: 比特奧定制報表系統
技術棧: Vue 3 + Element Plus + Vite (前端) + Spring Boot (后端)
開發模式: 前后端分離
項目結構: 單體倉庫包含前后端代碼
🏗? 項目架構分析
目錄結構設計
bitao-defined_report_ui/
├── src/ # 前端源碼
│ ├── api/ # API接口層
│ ├── components/ # 組件庫
│ │ ├── dict/ # 字典管理組件
│ │ ├── report/ # 報表管理組件
│ │ └── layout/ # 布局組件
│ ├── router/ # 路由配置
│ └── utils/ # 工具函數
├── backend/ # 后端源碼
│ └── bitao-defined-report/
└── public/ # 靜態資源
技術選型理由
- Vue 3: 組合式API,更好的TypeScript支持
- Element Plus: 成熟的UI組件庫,快速開發
- Vite: 快速的構建工具,熱更新體驗好
- Axios: HTTP客戶端,支持攔截器和請求/響應處理
🔄 前后端協作流程
1. API設計先行
后端API規范
// 統一響應格式
public class ApiResponse<T> {private String traceId; // 追蹤IDprivate boolean result; // 操作結果private int code; // 狀態碼private String msg; // 消息private T data; // 數據private boolean success; // 成功標識
}// 分頁參數基類
public class PageObject {private Integer pageNum = 1;private Integer pageSize = 10;private String isAsc = "desc";
}
前端API封裝
// api/reportApi.js
import request from '@/utils/request'/*** 獲取報表列表* @param {Object} params 查詢參數* @returns {Promise} API響應*/
export function getReportList(params) {return request({url: '/defined-report/report/selectByPage',method: 'post',data: params})
}
2. 數據類型對齊
關鍵經驗:類型一致性
場景 | 后端類型 | 前端處理 | 注意事項 |
---|---|---|---|
布爾狀態 | Boolean | null/true/false | 避免空字符串 |
分頁參數 | Integer | Number | 確保數值類型 |
時間字段 | LocalDateTime | String | 統一格式化 |
枚舉值 | Enum | String/Number | 保持值一致 |
實際案例:狀態字段處理
// ? 錯誤做法
const queryParams = {usableStatus: '' // 空字符串無法轉換為Boolean
}// ? 正確做法
const queryParams = {usableStatus: null // null表示不篩選,true/false表示具體狀態
}
🎨 組件開發模式
1. 頁面組件結構
標準頁面模板
<template><div class="page-container"><!-- 查詢表單 --><div class="search-form"><el-form :model="queryParams" :inline="true"><!-- 查詢條件 --></el-form></div><!-- 操作工具欄 --><div class="toolbar"><el-button type="primary" @click="handleAdd">新增</el-button></div><!-- 數據表格 --><el-table :data="dataList" v-loading="loading"><!-- 表格列 --></el-table><!-- 分頁組件 --><pagination v-model:page="queryParams.pageNum"v-model:limit="queryParams.pageSize":total="total"@pagination="getList"/></div>
</template><script setup>
import { reactive, ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'// 響應式數據
const loading = ref(false)
const dataList = ref([])
const total = ref(0)// 查詢參數
const queryParams = reactive({pageNum: 1,pageSize: 10,// 其他查詢字段
})// 獲取列表數據
const getList = async () => {loading.value = truetry {const response = await apiMethod(queryParams)if (response.code === 200) {dataList.value = response.data.data || []total.value = response.data.total || 0} else {ElMessage.error(response.message || '獲取數據失敗')}} catch (error) {console.error('獲取數據失敗:', error)ElMessage.error('網絡錯誤,請稍后重試')} finally {loading.value = false}
}// 頁面初始化
onMounted(() => {getList()
})
</script>
2. 組件復用策略
通用組件抽取
// components/pub/Pagination.vue - 分頁組件
// components/layout/AppHeader.vue - 頁面頭部
// components/layout/Sidebar.vue - 側邊欄
業務組件分類
// components/dict/ - 字典管理相關組件
// components/report/ - 報表管理相關組件
// ├── management/ - 報表列表管理
// ├── designer/ - 報表設計器
// └── preview/ - 報表預覽
🔧 開發工具配置
1. Vite配置優化
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, 'src')}},server: {port: 3000,proxy: {'/defined-report': {target: 'http://localhost:8080',changeOrigin: true}}}
})
2. 請求攔截器配置
// utils/request.js
import axios from 'axios'
import { ElMessage } from 'element-plus'const service = axios.create({baseURL: process.env.VUE_APP_BASE_API,timeout: 5000
})// 請求攔截器
service.interceptors.request.use(config => {// 添加token等通用處理return config},error => {console.log(error)return Promise.reject(error)}
)// 響應攔截器
service.interceptors.response.use(response => {const res = response.data// 統一錯誤處理if (res.code !== 200) {ElMessage.error(res.message || '系統錯誤')return Promise.reject(new Error(res.message || 'Error'))}return res},error => {console.log('err' + error)ElMessage.error(error.message)return Promise.reject(error)}
)export default service
🐛 常見問題與解決方案
1. 分頁查詢問題
問題描述
前端發送分頁請求時,后端返回"系統繁忙"錯誤
根本原因
- 參數類型不匹配(字符串 vs 布爾值)
- 缺少默認分頁參數
解決方案
// 前端:確保參數類型正確
const queryParams = reactive({pageNum: 1, // Number類型pageSize: 10, // Number類型usableStatus: null // null/Boolean類型
})
// 后端:添加默認構造函數
public ReportFormsPageParam() {super();this.setPageNum(1);this.setPageSize(10);this.setIsAsc("desc");
}
2. 狀態管理最佳實踐
組件內狀態
// 使用 reactive 管理表單數據
const formData = reactive({name: '',status: null
})// 使用 ref 管理簡單狀態
const loading = ref(false)
const visible = ref(false)
跨組件狀態
// 使用 provide/inject
// 父組件
provide('userInfo', userInfo)// 子組件
const userInfo = inject('userInfo')
📊 性能優化實踐
1. 組件懶加載
// router/index.js
const routes = [{path: '/report/list',component: () => import('@/components/report/management/ReportList.vue')}
]
2. 表格虛擬滾動
<!-- 大數據量表格優化 -->
<el-table-v2:columns="columns":data="data":width="700":height="400"fixed
/>
3. 請求防抖
import { debounce } from 'lodash-es'// 搜索防抖
const handleSearch = debounce(() => {getList()
}, 300)
🔍 調試與測試
1. 開發調試
// 開發環境日志
if (process.env.NODE_ENV === 'development') {console.log('API請求參數:', params)console.log('API響應數據:', response)
}
2. API測試
# 使用PowerShell測試API
Invoke-WebRequest -Uri 'http://localhost:3000/defined-report/report/selectByPage' `-Method POST `-ContentType 'application/json' `-Body '{"pageNum": 1, "pageSize": 10}'
📝 開發規范
1. 命名規范
- 文件命名: PascalCase (ReportList.vue)
- 組件名: PascalCase (ReportList)
- 方法名: camelCase (handleQuery)
- 常量名: UPPER_SNAKE_CASE (API_BASE_URL)
2. 代碼注釋
/*** 獲取報表列表數據* @param {Object} params 查詢參數* @param {Number} params.pageNum 頁碼* @param {Number} params.pageSize 每頁大小* @returns {Promise<Object>} 返回報表列表數據*/
const getReportList = async (params) => {// 實現邏輯
}
3. 錯誤處理
try {const response = await apiCall()// 成功處理
} catch (error) {console.error('操作失敗:', error)ElMessage.error('操作失敗,請稍后重試')// 錯誤恢復邏輯
}
🚀 部署與發布
1. 構建配置
// package.json
{"scripts": {"dev": "vite","build": "vite build","preview": "vite preview"}
}
2. 環境配置
// .env.development
VUE_APP_BASE_API = '/api'
VUE_APP_ENV = 'development'// .env.production
VUE_APP_BASE_API = 'https://api.example.com'
VUE_APP_ENV = 'production'
📈 項目總結
成功經驗
- 前后端類型對齊: 避免了大量的類型轉換問題
- 組件化開發: 提高了代碼復用性和維護性
- 統一錯誤處理: 提升了用戶體驗
- API層抽象: 便于接口管理和維護
改進建議
- 引入TypeScript: 提供更好的類型安全
- 添加單元測試: 保證代碼質量
- 性能監控: 添加性能指標收集
- 文檔完善: 建立完整的組件文檔
技術債務
- 部分組件耦合度較高,需要進一步解耦
- 缺少統一的狀態管理方案
- 錯誤邊界處理不夠完善
- 缺少自動化測試覆蓋
🎯 最佳實踐總結
- API優先設計: 前后端并行開發的基礎
- 類型一致性: 減少運行時錯誤的關鍵
- 組件化思維: 提高開發效率的核心
- 錯誤處理: 用戶體驗的重要保障
- 性能意識: 從開發階段就要考慮性能優化
- 文檔驅動: 良好的文檔是團隊協作的基礎
通過這個項目的實踐,我們建立了一套完整的前端開發流程和規范,為后續項目提供了寶貴的經驗和參考。