如何将数字123转化成大写的文字 一百二十三 或 一二三?

7,154 阅读4分钟

相信大家在前端开发过程中经常遇到需要显示章目的情况,例如:

Vue 中我们可以用 v-for 处理列表数据显示这样的列表,但是 我们只能通过 Index 获得 [0,1,2,3,4] ,显然我们需要的界面的序号是从1开始的,所以我们就需要将 index+1 可以得到 [1,2,3,4] ,这些 number 型的序号仅对于小节序号使用,那章节的 “一、二、三” 我们又该怎么实现呢?


1.转化成MATH类型的文字

对于一些比较简单的需求,也就是这个课程最多有十章,那就很简单了,我们就用数组把这些 “一、二、三。。。。”存起来,用遍历的index作为数组下标去取就行啦!具体实现代码也就两行:

js

const idxArray = ['一','二','三','四','五','六','七','八','九','十'];

html

<div v-for="(item,index) in catalogData">
    <span>第{{idxArray[index]}}章: {{item.courseChapterTitle}}</span>
</div>

这只是最简单的情况,也是局限性最大的情况,如果超过了十章了呢?就会出现undefined,所以我们需要一个可以转化所有小写数字的方法:

js

const numberChinese = (number) => {
  var units = '个十百千万@#%亿^&~', chars = '零一二三四五六七八九';
  var a = (number + '').split(''), s = []
  if (a.length > 12) {
    throw new Error('too big');
  } else {
    for (var i = 0, j = a.length - 1; i <= j; i++) {
      if (j == 1 || j == 5 || j == 9) {//两位数 处理特殊的 1*
        if (i == 0) {
          if (a[i] != '1') s.push(chars.charAt(a[i]));
        } else {
          s.push(chars.charAt(a[i]));
        }
      } else {
        s.push(chars.charAt(a[i]));
      }
      if (i != j) {
        s.push(units.charAt(j - i));
      }
    }
  }
  //return s;
  return s.join('').replace(/零([十百千万亿@#%^&~])/g, function (m, d, b) {//优先处理 零百 零千 等
    b = units.indexOf(d);
    if (b != -1) {
      if (d == '亿') return d;
      if (d == '万') return d;
      if (a[j - b] == '0') return '零'
    }
    return '';
  }).replace(/零+/g, '零').replace(/零([万亿])/g, function (m, b) {// 零百 零千处理后 可能出现 零零相连的 再处理结尾为零的
    return b;
  }).replace(/亿[万千百]/g, '亿').replace(/[零]$/, '').replace(/[@#%^&~]/g, function (m) {
    return { '@': '十', '#': '百', '%': '千', '^': '十', '&': '百', '~': '千' }[m];
  }).replace(/([亿万])([一-九])/g, function (m, d, b, c) {
    c = units.indexOf(d);
    if (c != -1) {
      if (a[j - c] == '0') return d + '零' + b
    }
    return m;
  });
}

html

<div v-for="(item,index) in catalogData">
    <span>第{{numberChinese(index+1)}}章: {{item.courseChapterTitle}}</span>
</div>

这种情况的话,加入我们传入的是 123 ,调用方法后,将输出 一百二十三 ,能够很好的表达我们的 第一百二十三章 ,不管你是有多少章都可以很好的转换啦!

2.转化成number类型的文字

对于程序猿来说,需求永远在变,你永远猜不到下一秒你的产品经理会让你改哪一个需求。有这样的情况,你得到的是“123”,但是你需要展现在给用户的是“一二三”,用上面的方法是不可以的了,那我们该怎么办呢?这种情况相对于上面的来说,要简单的多,我们只需这样做就可以完美的解决(大多数程序猿都会想到这样的方法,如果你没想到,说明你在js方面还有很大的进步空间):

js

  function numberChinese(number){
    const strNumber = number.toString();
    const len = strNumber.length;
    let numberCh = "";
    for(let i=0;i<len;i++){
     let currentNum = strNumber.substr(i,1);
     switch (currentNum) {
        case '0':
          numberCh += '零';
          break;
        case '1':
          numberCh += '一';
          break;
        case '2':
          numberCh += '二';
          break;
        case '3':
          numberCh += '三';
          break;
        case '4':
          numberCh += '四';
          break;
        case '5':
          numberCh += '五';
          break;
        case '6':
          numberCh += '六';
          break;
        case '7':
          numberCh += '七';
          break;
        case '8':
          numberCh += '八';
          break;
        case '9':
          numberCh += '九';
          break;
        default:
          numberCh += '*';
      }
    }
    return numberCh;
  }

html

<div>
    {{number}}的大写数字为:{{numberChinese(number)}}
</div>

就酱紫,数字 12345 就可以转换为 一二三四五 了,你以为这样写就很完美啦?no,no,no,你不觉得这样子写太复杂了吗?那么长的代码去实现这么个转化的小功能,心累,下面请不要眨眼,我们将用一行代码替换上面的四十多行代码:

(123456789).toLocaleString('zh-hans-CN-u-nu-hanidec',{useGrouping:false}) //"一二三四五六七八九"

是不是很想哭?原来可以这么简单!
useGrouping传入的 false 还是 true ,返回值有是有一定变化的哦!

toLocaleString 的方法详见 w3school,括号里具体的各种配置方法推荐看MDN的具体讲解!

就到这里啦!请大家多多指教!