自定义指令实现el-input-number的动态精度

问题描述:

elementUI的数字输入框组件el-input-number可以通过 :precision 属性设置精度,从而控制小数位数。但是产品给出的小数位数需求如下:

  1. 当数字是整数或者一位小数时,小数位自动补零,保持两位小数展示;
  2. 当数字是三位小数时,展示为三位小数;
  3. 当数字为四位小数时,展示为四位小数;
  4. 当数字超过四位小数时,四舍五入展示为四位小数。
    在这里插入图片描述

解决方案:

上述逻辑要求el-input-number组件不仅需要正确回写出数字的小数位,且能根据用户输入的数字动态变更el-input-number的精度,即precision 属性值。
考虑到项目中所有使用el-input-number的地方都需要改造成上述逻辑,所以决定采用自定义指令实现此动态精度的功能。这样不仅易于维护和扩展,且不容易和原先el-input-number组件上已绑定的事件及逻辑发生耦合。

代码:

1. 计算数字小数位数(精度)函数代码片

// 返回精度结果
export const calcPrecision = (inputNum, precision = 4) => {

  // 当inputNum为undefined或中文等特殊字符时,直接输出空字符串
  if (isNaN(Number(inputNum))) return '';

  const roundTo = (num, precision = 4) => {
    const factor = Math.pow(10, precision);
    return Math.round(num * factor) / factor;
  } // 计算出保留4位小数且四舍五入后的结果
  let num = roundTo(inputNum, precision);
  let pricisionNum;
  const numString = num.toString();
  const decimalIndex = numString.indexOf('.'); 
  let decimalPlaces = 0;
  if (decimalIndex !== -1) { // 当数字是小数时
    decimalPlaces = numString.length - decimalIndex - 1; // 返回小数位数
  }
  if (decimalPlaces < 2) {
    pricisionNum = 2; // 整数或不足两位小数,小数位数补为2位
  } else {
    pricisionNum = decimalPlaces;
  }
  return pricisionNum;
};

2. 自定义指令代码片

import Vue from 'vue';
import { calcPrecision } from ./utils'

// 注册一个数字输入框精度自定义指令 `v-precision`
Vue.directive('precision', {
  componentUpdated: function (el) {
    Vue.nextTick(()=>{
      /* 项目中部分el-input-number组件的value会有一些逻辑联动变化,
         因此获取value的逻辑写在nextTick里面,保证获取的value是最新的*/
      const inputEl = el.getElementsByClassName('el-input__inner')[0]
      const value = inputEl.value
      let num = calcPrecision(value) // 计算出当前el-input-number组件小数精度
      el.__vue__.precision = num // 赋值最新精度给el-input-number组件
    })
  },
  bind: function (el) {
    el.addEventListener('input', function () {
      const inputEl = el.getElementsByClassName('el-input__inner')[0]
      const value = inputEl.value
      let num = calcPrecision(value)
      el.__vue__.precision = num
    })
  },

  unbind: function (el) {
    el.removeEventListener('input', ()=>{});
  }
})

注意点及总结:

在上面自定义指令中,bind钩子是修改el-input-number组件数值时触发的,但是需要注意el-input-number组件初始化回写数据的时候,也需要根据数值计算出相应的精度,因此还需要componentUpdated钩子,保证首次渲染el-input-number组件时精度展示正确。

写在最后: 使用 el._vue_.precision = num 赋值在本地环境控制台中会触发强制赋值修改父组件的报错问题,因为线上环境不报错就暂时没有处理这个问题。如果读者知道解决办法,或者有更好的实现el-input-number动态精度的方案欢迎分享。
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值