解决 Vue 中大整数精度丢失问题 —— 以 degId 为例

在使用 Vue 进行前端开发时,我们常常会遇到从后端获取的大整数 ID(如 degId),这些 ID 在 JavaScript 中处理时可能会出现精度丢失的问题。本文将以一个实际案例说明这个问题,并提供解决方案。

🧨 问题描述

在项目文件 monthSatisfied.vue 的如下代码中:

1
2
3
4
5
let records = res.data.records;
if (records.length === 0) return;

// 更新 voteColumns,表示所有投票id
this.voteColumns = records.map(record => record.degId);

res.data.records 返回的数据中包含非常大的数字类型的 degId,例如:

1
2
3
4
{
"degId": 1935593557239328769,
...
}

但打印出的 voteColumns 却显示为:

1
[1935593557239328800, ...]

这表明 JavaScript 对大整数进行了自动精度转换,导致数据不准确。


❓ 原因分析

JavaScript 使用 IEEE-754 双精度浮点数格式来存储数值,其安全整数范围是:

1
2
Number.MIN_SAFE_INTEGER = -9007199254740991
Number.MAX_SAFE_INTEGER = 9007199254740991

而上面的 degId 超出了这个范围,因此会被自动“四舍五入”或“截断”,造成数据错误。


✅ 解决方案

方法一:前端手动将 degId 转换为字符串

这是最简单且实用的做法,适用于你无法修改后端接口的情况。

修改代码如下:

1
this.voteColumns = records.map(record => String(record.degId));

同时,在其他使用 record.degId 的地方也应统一转为字符串:

1
rowData[`dept_${String(record.degId)}`] = record.scores[index]?.score || '-';

这样可以确保键名一致,避免因为类型不同而导致数据查找失败。


方法二:后端返回字符串形式的 degId

如果你有权限修改后端接口,建议直接返回字符串类型的 degId

1
2
3
4
{
"degId": "1935593557239328769",
...
}

这样前端无需额外处理,从根本上解决了精度丢失问题。


🧪 示例对比

原始值 JS Number 类型输出 字符串处理后
1935593557239328769 1935593557239328800 "1935593557239328769"

可以看到,使用字符串是最稳妥的方式。


📌 总结

问题原因 解决方法
degId 是超大整数,超出 JS 数值精度范围 后端返回字符串类型或前端手动转换为字符串
前端解析 degId 时精度丢失 所有涉及 degId 的地方统一用字符串处理

💡 推荐做法(最佳实践)

✅ 如果你能控制后端接口,优先让后端返回字符串类型的 ID:

1
"degId": "1935593557239328769"

🚫 不推荐继续使用 Number 处理超大整数,容易引发不可预知的 bug。


🧩 拓展阅读