前端获取接口数据流程
一、Free-Table组件分析
<free-table
v-show="showTable"
v-model:page="params.pageNum" 双向绑定当前页大小,支持动态更新
v-model:limit="params.pageSize" 双向绑定每页大小,支持动态更新
v-loading="tableLoading" 显示加载动画
:data="tableList" 绑定表格数据
:column="realTableColumn" 定义表格列的配置
:total="total" 数据总条数,用于计算分页页数
:page-size="params.pageSize" 每页显示的条数
:height="tableHeight" 设置表格高度(需自定义数值)
:header-cell-style="{ background: '#F9F9FA' }" 自定义表头单元格的样式。
:class="densityClass" 动态绑定表格样式类,支持表格密度切换
pagination 启用分页功能
border 启用表格边框
stripe 启用斑马纹样式
@pagination="getTableList" 分页控件触发时调用的方法,通常用于重新加载数据
/>
二、组件初始化阶段
1、初始化响应式状态对象:tablebody。
2、核心状态:
-
表格高度 ( tableHeight )
-
数据加载状态 ( tableLoading )
-
表格数据 ( tableList )
-
总条数 ( total )
-
分页参数 ( params ):设置默认分页参数。(第1页,每页50条)
const tableBody = reactive<stateType>({tableHeight: 600,showTable: true,tableLoading: false,tableList: [],total: 0,params: {pageNum: 1,pageSize: 50, // 默认每页50条},
});
三、表单和表格配置
1、表单字段:
通过 getFormFields 获取表单配置:
const formDataModel = reactive({});const formData = computed(() => ({showButtons: false,confirmText: '查询',model: formDataModel, // 绑定表单数据模型fields: getFormFields(), // 获取表单字段配置
}));
getFormFields() 返回的表单配置:
[{ prop: 'dw', type: 'input', placeholder: '单位' },{ prop: 'yd', type: 'datePicker', placeholder: '月度' }
]
2、表格列:
通过 getTableColumn 获取表格列配置:
const tableColumn = getTableColumn();
四、组件挂载自动加载数据
onMounted(init); // 组件挂载时触发数据加载
const init = () => {getTableList();
};
五、核心数据获取方法
const getTableList = async () => {try {tableBody.tableLoading = true;// 合并分页参数和表单参数const params = {...tableBody.params,...formDataModel};const res: any = await getInfoApi(params);if (res.status === 200) {tableBody.tableList = res.data.records || [];tableBody.total = res.data.total ? Number(res.data.total) : 0;} else {ElMessage.warning(res.message);}} finally {tableBody.tableLoading = false;}
};
注:其中 res.status 的 status 为状态名,
不同接口可能会有不同的状态名(如code等),所以需要根据不同情况进行修改 。
1、参数合并策略
const params = {...tableBody.params, // 分页参数 { pageNum: 1, pageSize: 50 }...formDataModel // 表单参数 { dw: '单位A', yd: ['2023-01', '2023-06'] }
};
合并后的请求参数示例:
{"pageNum": 1,"pageSize": 50,"dw": "单位A","yd": ["2023-01", "2023-06"]
}
2、多种解构方式
功能/解构方式 | 直接解构:data.rows | 对象访问:res.data.rows |
API调用 | const { data, code, message } = await pageApi(params); | const res: any = await getInfoApi(params); |
状态码检查 | if (code === 200) | if (res.status === 200) |
数据赋值 | tableBody.tableList = data.rows; | tableBody.tableList = res.data.records; |
3、响应数据处理
1.直接赋值
特点:保持原始结构 + 分页信息。
其中records要与接口返回的数组名一致。
如若是"list": [...],那么就得是res.data.list。
tableBody.tableList = res.data.records || []; // 表格数据
tableBody.total = Number(res.data.total) || 0; // 总数
假设后端返回数据结构:
{"status": 200,"data": {"records": [...], // 当前页数据"total": 1250 // 总记录数}
}
2.字段映射
特点:必须转换 + 空安全
orgTypeList.value = (data as OrgItem[]).map(item => ({label: item.name,value: item.id,
转换过程:
// 原始数据
[{ name: "米哈油", id: "org-001" }]
// 转换后(丢弃id,保留label/value)
[{ label: "米哈油", value: "org-001" }]
为什么一定要转换为 { label, value } 格式?
- 适配 UI 组件的数据格式
- 统一处理逻辑
- 减少不必要的数据处理
- 清晰分离显示值与存储值
在少数简单场景下可以直接使用原始数据:
- 纯字符串/数字的简单列表
- 组件明确支持自定义字段映射
六、用户交互触发点
1、查询按钮
const submitHandler = () => {console.log('Form Data Model:', formDataModel);init(); // 触发数据加载
};
2、数据统计按钮
const dataStatistics = () => {init(); // 同样触发数据加载
};
3、表格刷新/分页
注:该代码所在文件位置:index.vue。
<!-- Template中 -->
<table-operate @on-refresh="getTableList"/>
<free-table @pagination="getTableList"/>
七、动态列显示
按需求选择哪些列显示,哪些列不显示。
1. 表格操作组件引用index
<table-operate ref="tableOperateRef" :table-column="tableColumn"@on-refresh="getTableList">
</table-operate>
2. 动态列计算属性hooks
const realTableColumn = computed(() => tableOperateRef.value?.realTableColumn ?? []
);
3. 表格组件绑定index
<free-table :column="realTableColumn"></free-table>