利用指令实现对输入框千分位的处理

2,788 阅读1分钟

最近碰到一个需求,输入框(el-input)输入时显示千分位格式,但发送请求的参数是不带千分位的 这个考虑到这个输入框输入的数字还需要影响其他几列数据的变化(其他列的数据由此输入计算得出),需要在计算时多次去掉千分位,且发送给请求时也需要循环每一行去去除千分位标识符 因为不想做上述重复的处理,决定使用指令实现需求,实现的效果是,输入框内显示的是千分位,但实际上绑定的值是没有千分位字符

效果如下

687zxx.png

代码

<template>
  <div id="app">
    <el-button @click="edit=!edit">点击</el-button>
    <template>
      <el-table
         :data="tableData"
         style="width: 100%"
         height="1050">
        <el-table-column
         prop="zip"
         label="输入时显示千分位,但v-model绑定的值是没有千分位的"
         width="400">
          <template slot-scope="scope">
            <div v-if="!edit">{{scope.row.thousandShow}}</div>
            <el-input v-else v-thousandFormat.thousandShow="scope.row"  v-model="scope.row.thousandShow"></el-input>
            <div>实际发送绑定thousandShow的值一直是<span style="color: #ff0000;">{{scope.row.thousandShow}}</span></div>
          </template>
        </el-table-column>
      </el-table>
    </template>
  </div>
</template>

<script>
/* eslint-disable */
export default {
  mounted(){
    setTimeout(() => {
        this.tableData = [{
            thousandShow:"2222222",
        },{
            thousandShow:"8888888",
        },{
            thousandShow:"33333333",
        }]
    }, 1000);
  },
  directives:{
     thousandFormat:{
       bind(el, binding, vnode){
         let event = new Event('input');
         function numFormat(num){
             let num1 = num.split(".")[0]
             let num2 = num.split(".")[1]
             let c = num1.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
             if(num.toString().indexOf(".")!==-1){
                 return c+"."+num2
             }
             else {
                 return c
             }
         }
         let key = Object.keys(binding.modifiers)[0]
         el.addEventListener("input",function (event) {
            let inputValue = binding.value[key]
            let cursorPos = event.target.selectionStart||0;
            // 以从后数起来说,光标位置是不变的
            let curPosFromBack = inputValue.length - cursorPos
            let inpVal = inputValue =  inputValue.replace(/,/g,"")
            binding.value[key] = inpVal //这里变化会导致视图变化
            let t =  numFormat(inpVal) //转换为千分位格式
            vnode.context.$nextTick(function () {
               el.querySelector('input').value = t //在上面由于value变化而更新视图后,再赋值给input.value,
                                      //这样可以防止这次赋值先于上面的更新视图执行
                //这里重新将光标的位置重置到输入数字的位置,否则每次正则变换后光标总是跳到最后
               el.querySelector('input').setSelectionRange(t.length-curPosFromBack, t.length-curPosFromBack);
                                  
            })
         })
         el.dispatchEvent(event); //如果数据从服务端获取,要自定义input事件发送,这样才能触发上面绑定的事件处理方法,使数据一进入输入框里面变成千分位格式
       }
     }
  },
  data() {
    return {
      tableData: [{
          thousandShow:"",
      },{
          thousandShow:"",
      }],
      edit:false
    }
  }
}
</script>

代码地址