VUE3使用elementplus实现数字的复杂运算(完善中)

VUE3使用elementplus实现数字的复杂运算(完善中)

一、官方推荐

在 Vue3 中处理嵌套数组或循环计算时,可通过以下方式优化复杂数字运算逻辑:

1. ‌利用计算属性(computed)处理响应式数据

在<script setup>语法糖中,对于依赖响应式数据的计算,优先使用 computed 自动追踪依赖并缓存结果‌:

const numbers = ref([4, 15, 1, 8]);  
const sum = computed(() => numbers.value.reduce((acc, num) => acc + num, 0));  

支持多层嵌套数组的聚合计算:

const nestedNumbers = ref([[12, 4], [3, 6]]);  
const complexResult = computed(() =>  
  nestedNumbers.value.flat().reduce((acc, num) => (acc * num) / 2, 1)  
);  

2. ‌通过 reduce 实现循环计算

对数组或嵌套结构进行累加、累乘等操作‌:

// 示例:计算 ((12+4)*3)/6  
const steps = [12, 4, 3, 6];  
const result = steps.reduce((acc, val, index) => {  
  if (index === 0) return val;  
  if (index === 1) return acc + val;  
  if (index === 2) return acc * val;  
  return acc / val;  
}, 0);  

3. ‌递归处理嵌套数组

使用递归函数遍历嵌套数组结构并执行计算‌:

function deepCalculate(arr: any[]): number {  
  return arr.reduce((acc, item) => {  
    if (Array.isArray(item)) {  
      return acc + deepCalculate(item);  
    }  
    return acc + Number(item);  
  }, 0);  
}  
// 使用示例  
const nestedArray = [[4, [15, 1]], 8];  
const total = deepCalculate(nestedArray);  // 4+15+1+8=28  

4. ‌使用工具库简化复杂运算

  • 引入 lodash 或 math.js 处理高阶数学逻辑:
import { chain } from 'lodash';  
const result = chain([4, 15, 1, 8])  
  .sum()  
  .multiply(2)  
  .value();  // (4+15+1+8)*2=56  

二、实际应用

1、简单数字的运算,两数加减乘除,使用原始JS方法写在公共TS文件中,使用时调用

/**加法*/
export const NumberAdd=(arg1:any, arg2:any)=> {
    var r1, r2, m, n;
    try {
        r1 = arg1.toString().split(".")[1].length
    } catch (e) {
        r1 = 0
    }
    try {
        r2 = arg2.toString().split(".")[1].length
    } catch (e) { 
        r2 = 0 
    } 
    m = Math.pow(10, Math.max(r1, r2))
    n = (r1 >= r2) ? r1 : r2;
    return ((arg1 * m + arg2 * m) / m).toFixed(n);
}
/**减法*/
export const NumberSub=(arg1:any, arg2:any)=> {
    var re1, re2, m, n;
    try {
        re1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    re1 = 0;
    }
    try {
        re2 = arg2.toString().split(".")[1].length;
    } catch (e) {
        re2 = 0;
    }
    m = Math.pow(10, Math.max(re1, re2)); 
    n = (re1 >= re2) ? re1 : re2;
    return ((arg1 * m - arg2 * m) / m).toFixed(n);
}
/**乘法*/
export const NumberMul=(arg1:any, arg2:any)=> {
    var m = 0;
    var s1 = arg1.toString();
    var s2 = arg2.toString();
    try {
        m += s1.split(".")[1].length;
    } catch (e) {}
    try {
        m += s2.split(".")[1].length;
    } catch (e) {}
 
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}
/**除法(除数,被除数,保留的小数点后的位数 )*/
export const NumberDiv=(arg1:any, arg2:any,digit:any)=> {
    var t1=0,t2=0,r1,r2;
    try{t1=arg1.toString().split(".")[1].length}catch(e){}
    try{t2=arg2.toString().split(".")[1].length}catch(e){}
    r1=Number(arg1.toString().replace(".",""))
    r2=Number(arg2.toString().replace(".",""))
    //获取小数点后的计算值
    var result= ((r1/r2)*Math.pow(10,t2-t1)).toString()
    var result2=result.split(".")[1];

    var result3 = 0;
    if(result2 != undefined)
    {
        result2 = result2.substring(0,digit>result2.length?result2.length:digit);
        result3 = Number(result.split(".")[0]+"."+result2);
    }
    else
    {
        result3 = Number(result);
    }
    return result3;
}
//加法
let aaa = Number(NumberAdd(12,13));

若参与运算的是一些FORM表单中的字段,而FORM表单又没有使用接口定义它包含的字段名称及其类型,则可以使用该方法直接调用,不需要使用其他方法先定义数字number类型。因为没有定义表单内容时,每一步对表单中字段的运算操作都需要定义或使用Number进行转换,比较麻烦。

如果不想通过以上方式实现两数字的加减乘除,可以使用官方推荐的方法。

2、如果遇到复杂运算,可以使用官方推荐的newFunction,尽量不要使用eval函数,如下图为封装到TS文件中的简化版。

/**方便实现动态表达式计算 */
export const calculate = (expression: string) => {  
    try {  
      return new Function(`return ${expression}`)();  
    } catch {  
      return NaN;  
    }  
  };  
let a = ((15*12*13*2)/8)-7;
const result = Number(calculate(a));

3、如果参加运算的参数已经定义了类型是number类型,则可以直接参与运算,但一定要确保全局定义了number类型,比如同时使用FORM表单定义实体类(字段类型+字段名称)+<el-input-number>控件控制字段一定是数字类型输入,否则可能会出现某一步变成字符串拼接的情况。

而且要注意表单中字段实现了响应式数据,因此页面某个地方对字段做出不合理的赋值,比如赋值了非数字,则直接运算会出错。

//举例:
const a = ref<number>(10);//当ref括号内一定是数字时,前面的<number>可省略
const b = ref<number>(20);//当ref括号内一定是数字时,前面的<number>可省略
let c = a+b;//结果也是number类型