直接上代码
1 <template>
2 <!-- 定义一个 Element UI 的输入框组件 -->
3 <el-input
4 v-model="formattedValue"
5 @input="handleInput"
6 @change="handleChange"
7 ></el-input>
8 </template>
1 <script>
2 /**
3 * MyFormattedInput 组件,用于格式化输入的数字,并添加千分位分隔符
4 *
5 * @props {Number|String} value - 输入的值,默认为 0
6 */
7 export default {
8 // 组件名称
9 name: "MyFormattedInput",
10 // 定义组件的 props
11 props: {
12 value: {
13 // 支持的类型为数字或字符串
14 type: [Number, String],
15 // 默认值为 0
16 default: 0,
17 },
18 },
19 // 计算属性
20 computed: {
21 formattedValue: {
22 /**
23 * 获取格式化后的值
24 *
25 * @returns {String} 格式化后的字符串,添加了千分位分隔符
26 */
27 get() {
28 // 打印获取值时的日志
29 console.log("get", this.value);
30 // 将值转换为字符串,并添加千分位分隔符
31 return this.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
32 },
33 /**
34 * 设置格式化后的值,并触发 input 事件
35 *
36 * @param {String} formattedValue - 格式化后的值
37 */
38 set(formattedValue) {
39 // 打印设置值时的日志
40 console.log("set", formattedValue);
41 // 获取小数点的索引
42 const pointIndex = formattedValue.indexOf(".");
43 // 判断最后一个字符是否为小数点
44 const hasLastPoint = formattedValue[formattedValue.length - 1] === ".";
45 // 判断是否包含小数点
46 const hasPoint = formattedValue.includes(".");
47 if (hasPoint && hasLastPoint) {
48 // 如果包含小数点且最后一个字符是小数点,移除逗号并触发 input 事件
49 this.$emit("input", formattedValue.replace(/,/g, ""));
50 } else if (hasPoint && !hasLastPoint) {
51 if (formattedValue.length - 2 > pointIndex) {
52 // 如果包含小数点且有足够的小数位数,移除逗号并保留两位小数
53 this.$emit(
54 "input",
55 this.toFixedNoRound(parseFloat(formattedValue.replace(/,/g, "")), 2)
56 );
57 } else {
58 // 如果小数位数不足,移除逗号并触发 input 事件
59 this.$emit("input", formattedValue.replace(/,/g, ""));
60 }
61 } else {
62 // 如果不包含小数点,移除逗号并转换为数字,若为 NaN 则为 0
63 this.$emit(
64 "input",
65 parseFloat(formattedValue.replace(/,/g, "")) || 0
66 );
67 }
68 },
69 },
70 },
71 // 组件的方法
72 methods: {
73 /**
74 * 处理输入事件
75 *
76 * @param {String} value - 输入的值
77 */
78 handleInput(value) {
79 // 打印输入事件的日志
80 console.log("handleInput", value);
81 // 计算小数点出现的次数
82 var pointShowCount = value.split(".").length - 1;
83 if (pointShowCount == 0 || pointShowCount == 1) {
84 // 如果小数点出现 0 或 1 次
85 if (isNaN(parseFloat(value.replace(/,/g, "")))) {
86 // 如果移除逗号后不是数字,触发 input 事件并传入 0
87 this.$emit("input", 0);
88 }
89 }
90 },
91 /**
92 * 处理值改变事件
93 *
94 * @param {String} value - 改变后的值
95 */
96 handleChange(value) {
97 // 打印值改变事件的日志
98 console.log("handleChange", value);
99 if (isNaN(parseFloat(value.replace(/,/g, "")))) {
100 // 如果移除逗号后不是数字,触发 change 事件并传入 0
101 this.$emit("change", 0);
102 } else {
103 // 如果是数字,移除逗号并转换为数字,若为 NaN 则为 0
104 this.$emit("change", parseFloat(value.replace(/,/g, "")) || 0);
105 }
106 },
107 /**
108 * 截取指定小数位数,不进行四舍五入
109 *
110 * @param {Number} num - 要处理的数字
111 * @param {Number} decimals - 保留的小数位数
112 * @returns {String} 处理后的字符串,保留指定小数位数
113 */
114 toFixedNoRound(num, decimals) {
115 // 计算乘数
116 const multiplier = Math.pow(10, decimals);
117 // 截取小数部分
118 const truncatedNum = Math.trunc(num * multiplier) / multiplier;
119 // 转换为字符串并保留指定小数位数
120 return truncatedNum.toFixed(decimals);
121 },
122 },
123 };
124 </script>
get()
方法:将this.value
转换为字符串,并使用正则表达式/\B(?=(\d{3})+(?!\d))/g
添加千分位分隔符。set()
方法:根据输入值的不同情况处理小数点和小数位数,并触发input
事件。
handleInput(value)
:处理输入事件,计算小数点出现的次数,若移除逗号后不是数字,则触发input
事件并传入 0。handleChange(value)
:处理值改变事件,若移除逗号后不是数字,则触发change
事件并传入 0;否则,移除逗号并转换为数字,若为NaN
则为 0。toFixedNoRound(num, decimals)
:截取指定小数位数,不进行四舍五入。