彻底搞懂 TDesign Vue Next 数字输入框 decimalPlaces 属性:从类型陷阱到最佳实践

彻底搞懂 TDesign Vue Next 数字输入框 decimalPlaces 属性:从类型陷阱到最佳实践

【免费下载链接】tdesign-vue-next A Vue3.x UI components lib for TDesign. 【免费下载链接】tdesign-vue-next 项目地址: https://gitcode.com/gh_mirrors/tde/tdesign-vue-next

你是否在使用 TDesign Vue Next 数字输入框时,遇到过 decimalPlaces 属性设置不生效的问题?或者对它同时支持 number 和 object 两种类型感到困惑?本文将从类型定义、实现原理到实战案例,全面解析 decimalPlaces 的设计逻辑与避坑指南,帮你彻底掌握这个高频使用却极易出错的属性。

一、属性类型解析:为什么 decimalPlaces 支持两种类型?

1.1 基础类型定义揭秘

TDesign Vue Next 数字输入框(InputNumber)的 decimalPlaces 属性在类型定义文件(type.ts)中被明确定义为联合类型:

// packages/components/input-number/type.ts 核心定义
export type InputNumberDecimalPlaces = number | { 
  enableRound: boolean;  // 是否启用四舍五入
  places: number;        // 小数位数
};

这种设计源于实际开发中的两种常见需求:

  • 简单场景:仅需指定固定小数位数(如保留2位小数)
  • 复杂场景:需要精确控制四舍五入行为(如金融场景需截断而非四舍五入)

1.2 两种类型的本质区别

通过 props.ts 文件可以看到属性的校验逻辑:

// packages/components/input-number/props.ts 类型校验
decimalPlaces: {
  type: [Number, Object] as PropType<TdInputNumberProps['decimalPlaces']>,
  default: undefined as TdInputNumberProps['decimalPlaces'],
},
类型适用场景内部处理逻辑
number快速设置小数位数,自动四舍五入等价于 { enableRound: true, places: number }
object需要关闭四舍五入或动态调整舍入策略显式控制四舍五入行为

二、实现原理:decimalPlaces 如何影响数值处理?

2.1 核心处理流程

从测试用例和组件源码可以推断出 decimalPlaces 的处理流程:

mermaid

2.2 关键代码实现

虽然无法获取完整的格式化函数代码,但从测试用例可以反推出核心逻辑:

// 推断的格式化函数逻辑
function formatNumber(value, decimalPlaces) {
  let { places, enableRound = true } = 
    typeof decimalPlaces === 'number' 
      ? { places: decimalPlaces, enableRound: true } 
      : decimalPlaces;
  
  if (enableRound) {
    return Number(value).toFixed(places);
  } else {
    const [integerPart, decimalPart] = String(value).split('.');
    return decimalPart 
      ? `${integerPart}.${decimalPart.slice(0, places)}` 
      : integerPart;
  }
}

三、实战指南:decimalPlaces 正确用法与避坑

3.1 基础用法:数字类型设置

最简单的保留指定位数小数(默认四舍五入):

<template>
  <TInputNumber 
    v-model="price" 
    :decimal-places="2" 
    placeholder="保留两位小数"
  />
</template>

<script setup>
import { ref } from 'vue';
const price = ref(99.99); // 显示为 99.99
</script>

3.2 高级用法:对象类型精确控制

金融场景中常见的截断需求(不四舍五入):

<template>
  <TInputNumber 
    v-model="amount" 
    :decimal-places="{ places: 2, enableRound: false }" 
    placeholder="截断至两位小数"
  />
</template>

<script setup>
import { ref } from 'vue';
const amount = ref(100.1234); // 显示为 100.12(而非四舍五入的 100.12)
</script>

3.3 大数场景特殊处理

当启用 largeNumber 模式时,decimalPlaces 仍正常工作:

<template>
  <TInputNumber 
    v-model="largeValue" 
    :decimal-places="{ places: 0, enableRound: true }" 
    large-number
    placeholder="大数四舍五入取整"
  />
</template>

<script setup>
import { ref } from 'vue';
const largeValue = ref("9999999999999999.5"); // 显示为 10000000000000000
</script>

四、避坑指南:常见问题与解决方案

4.1 类型错误导致不生效

问题表现:设置 decimalPlaces 后无任何效果
原因分析:误将对象属性名写错(如 place 而非 places)
解决方案

// 错误示例
{ enableRound: false, place: 2 } // 属性名应为 places

// 正确示例
{ enableRound: false, places: 2 }

4.2 四舍五入与截断混淆

问题表现:需要精确截断却得到四舍五入结果
解决方案:显式设置 enableRound: false

<!-- 错误用法 -->
<TInputNumber :decimal-places="2" /> <!-- 自动四舍五入 -->

<!-- 正确用法 -->
<TInputNumber :decimal-places="{ places: 2, enableRound: false }" />

4.3 与 largeNumber 一起使用时的类型问题

问题表现:大数场景下小数位数设置失效
原因分析:大数模式下 value 必须为字符串类型
解决方案

<TInputNumber 
  v-model="largeValue" 
  :decimal-places="2" 
  large-number 
/>

<script setup>
const largeValue = ref("1234567890123456.789"); // 正确:字符串类型
// const largeValue = ref(1234567890123456.789); // 错误:数值类型会丢失精度
</script>

五、测试验证:确保 decimalPlaces 行为符合预期

5.1 单元测试关键用例

从 input-number.test.tsx 中提取的核心测试用例:

// 数值类型测试
it(':decimalPlaces', () => {
  const value = ref('100');
  const wrapper = mount(() => <InputNumber v-model={value.value} decimalPlaces={2} />);
  const input = wrapper.find('.t-input input');
  expect(input.element.value).toBe('100.00');
});

// 对象类型测试
it(':decimalPlaces: { enableRound: boolean }', () => {
  const value3 = ref('1.356');
  const wrapper3 = mount(() => (
    <InputNumber v-model={value3.value} decimalPlaces={{ places: 2 }} />
  ));
  expect(wrapper3.find('.t-input input').element.value).toBe('1.36'); // 四舍五入

  const value4 = ref('1.356');
  const wrapper4 = mount(() => (
    <InputNumber v-model={value4.value} decimalPlaces={{ enableRound: false, places: 2 }} />
  ));
  expect(wrapper4.find('.t-input input').element.value).toBe('1.35'); // 截断
});

5.2 手动测试 checklist

使用组件时建议验证以下场景:

  •  小数位数为 0 时的整数处理
  •  输入超过指定小数位的数字
  •  负数场景下的小数处理
  •  空值或 undefined 时的表现
  •  与 max/min 限制同时使用的情况

六、最佳实践总结

6.1 类型选择决策指南

mermaid

6.2 代码规范建议

  1. 明确类型注释:当使用 object 类型时添加详细注释
<TInputNumber 
  v-model="value" 
  :decimal-places="{ 
    places: 2, 
    enableRound: false  // 数值计算需精确截断,禁用四舍五入
  }" 
/>
  1. 统一配置管理:复杂场景下提取为常量
// constants.js
export const DECIMAL_CONFIG = {
  MONEY: { places: 2, enableRound: true }, // 金额:保留2位小数并四舍五入
  CALCULATION: { places: 4, enableRound: false },   // 计算:保留4位小数并截断
};

// 组件中使用
import { DECIMAL_CONFIG } from '@/constants';
<TInputNumber :decimal-places="DECIMAL_CONFIG.MONEY" />
  1. 结合 format 自定义格式化:复杂场景组合使用 decimalPlaces 和 format
<TInputNumber 
  v-model="value" 
  :decimal-places="2"
  :format="(value) => `$${value}`"
/>

七、总结与展望

decimalPlaces 属性作为 TDesign Vue Next 数字输入框的核心功能,其双类型设计既满足了简单场景的快速使用,又提供了复杂场景的精确控制。通过本文的解析,相信你已经掌握了:

  • decimalPlaces 两种类型的区别与应用场景
  • 四舍五入与截断的实现原理
  • 常见错误的识别与解决方法
  • 符合工程化规范的最佳实践

在未来使用数字输入框时,建议根据实际业务场景选择合适的类型配置,并通过单元测试确保 decimalPlaces 行为符合预期。对于金融、计算等对精度要求极高的场景,务必结合 largeNumber 属性和字符串类型值使用,避免 JavaScript 数值精度问题带来的风险。

掌握 decimalPlaces,让你的数字输入交互既精准又优雅!

收藏本文,下次遇到数字输入框小数处理问题,直接对照指南快速解决!关注作者获取更多 TDesign 组件深度解析。

【免费下载链接】tdesign-vue-next A Vue3.x UI components lib for TDesign. 【免费下载链接】tdesign-vue-next 项目地址: https://gitcode.com/gh_mirrors/tde/tdesign-vue-next

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值