在elementUI基础上改造input组件

312 阅读1分钟
<script>
import input from 'element-ui/lib/input.js';
import XEUtils from 'xe-utils';
const propKeys = Object.keys(input.props);
const methods = {};
Object.keys(input.methods).forEach(name => {
  methods[name] = function (...args) {
    return this.$refs.inputNumber && this.$refs.inputNumber[name](...args);
  };
});
export default {
  name: 'InputNumber',
  props: {
    ...input.props,
    // eslint-disable-next-line vue/require-default-prop
    value: [String, Number],
    // eslint-disable-next-line vue/require-default-prop
    digits: [Number],
    // eslint-disable-next-line vue/require-default-prop
    max: Number,
    // eslint-disable-next-line vue/require-default-prop
    min: Number
  },
  data() {
    return {
      inputType: 'text'
    };
  },
  computed: {
    formatterValue() {
      const { value, inputType } = this;
      if (value && inputType !== 'number') {
        return this.value.toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','));
      }
      return this.value;
    },
    inputPros() {
      return propKeys.reduce((obj, key) => {
        obj[key] = this[key];
        return obj;
      }, {});
    }
  },
  mounted() {
    const vnode = this.$refs.inputNumber;
    vnode.$on('focus', e => {
      this.inputType = 'number';
      this.$emit('focus', e);
    });
    vnode.$on('change', e => {
      // render 渲染inputNumber 拿不到 $listeners 的change
      !this.$listeners.change && this.$emit('change', e);
    });
    vnode.$on('blur', e => {
      this.inputType = 'text';
      this.$emit('blur', e);
    });
    /**
     * 最大最小值限制
     */
    vnode.$on('input', val => {
      if (this.max !== undefined && this.max < val && val !== '') {
        val = this.max;
        this.$message.error(`最大值${val}`);
      }
      if (this.min !== undefined && this.min > val && val !== '') {
        val = this.min;
        this.$message.error(`最小值${val}`);
      }
      //小數點限制
      if (this.digits !== undefined && val) {
        const len = (String(val).split('.')[1] || '').length;
        if (len > this.digits) {
          const regexp = new RegExp(`(?<value>^(-)?\d+\.(?:(\d){0,${this.digits}))`);
          val = Number(val.toString().match(regexp).groups.value);
          // val = Number(XEUtils.toFixed(val, this.digits));
        }
      }
      this.$emit('input', val);
    });
  },
  methods,
  render(h) {
    const { suffix, prefix, append, prepend } = this.$slots;
    const childs = [];
    prefix && childs.push(h('span', { slot: 'prefix' }, suffix));
    prepend && childs.push(h('span', { slot: 'prepend' }, prepend));
    suffix && childs.push(h('span', { slot: 'suffix' }, suffix));
    append && childs.push(h('span', { slot: 'append' }, append));
    return h(
      'el-input',
      {
        ref: 'inputNumber',
        on: this.$listeners,
        nativeOn: {
          mousewheel: e => {
            e.preventDefault();
            e.stopPropagation();
          },
          paste: e => {
            this.$emit('paste', e);
          },
          keydown: e => {
            const keyCode = e.keyCode;
            if (keyCode === 38 || keyCode === 40) e.preventDefault();
          }
        },
        attrs: {
          placeholder: this.$attrs.placeholder,
          step: 'any'
        },
        props: {
          ...this.inputPros,
          type: this.inputType,
          value: this.formatterValue
        }
      },
      childs
    );
  }
};
</script>