Element分析(组件篇)—— InputNumber

input-number组件是用来输入数字的,也不是很复杂。

最外层

最外层是一个div.el-input-number,上面有一些动态的class

size

size是一个prop,用来控制其大小的。

props: {
  size: String,
}

disabled

disabled也是prop,用来控制是否禁用。

props: {
  disabled: Boolean,
}

controls

controls也是prop,用来控制是否有控制器。

props: {
  controls: {
    type: Boolean,
    default: true
  }
}

减少按钮

减少按钮是一个span



minDisabled

minDisabled是一个计算属性,用来控制是否禁用该按钮。

computed: {
  minDisabled() {
    return this.accSub(this.value, this.step) < this.min;
  },
}

v-repeat-click

v-repeat-click是一个指令,用来控制左键按下时不断触发事件。

directives: {
  repeatClick: {
    bind(el, binding, vnode) {
      let interval = null;  // 定时器
      let startTime;

      const handler = () => vnode.context[binding.expression]();  // 获取表达式的内容

      const clear = () => {
        // 如果当前时间距离开始时间少于 100ms,执行 handler
        if (new Date() - startTime < 100) {
          handler();
        }
        // 清除计时器
        clearInterval(interval);
        interval = null;
      };

      // 绑定鼠标点击下的事件
      on(el, 'mousedown', () => {
        startTime = new Date();  // 更新当前时间
        once(document, 'mouseup', clear);  // 给鼠标抬起绑定一次性事件 clear
        interval = setInterval(handler, 100);  // 开始定时器
      });
    }
  }
},

decrease

控制数值减少。

methods: {
  decrease() {
    if (this.minDisabled) return;  // 如果减少按钮不可以用,直接返回
    const value = this.value || 0;  // 默认为0
    if (this.accSub(value, this.step) < this.min || this.disabled) return;  // 如果减少后小于最小值,或者当前input不可用都直接返回
    this.currentValue = this.accSub(value, this.step);  // 否则设置新的值
  },
}

其中accSub是另一个用来做减法的方法,用来处理小数的精度问题。

methods: {
  // arg1 当前值
  // arg2 步进值
  accSub(arg1, arg2) {
    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 parseFloat(((arg1 * m - arg2 * m) / m).toFixed(n));
  },
}

增加按钮

增加按钮也是一个span,绝大多数逻辑和减少按钮一样,只是减法变成加法,在此不再进行赘述。

el-input

最后是内嵌了一个el-input来实现输入框,并且进行了处理可以将input-number的具名slotappendprepend传入el-input中,这样可以更好地复用。


    
     

这里只有handleBlur没有解释过,它会设置el-input的值。

methods: {
  handleBlur() {
    this.$refs.input.setCurrentValue(this.currentValue);
  }
}

其他

data

初始化的时候,修正value

data() {
  let value = this.value;

  // 如果输入值小于最小值,则设为最小值
  if (value < this.min) {
    this.$emit('input', this.min);
    value = this.min;
  }

  // 如果输入值大于最大值,则设为最大值
  if (value > this.max) {
    this.$emit('input', this.max);
    value = this.max;
  }
  return {
    currentValue: value
  };
},

watch

watch: {
value(val) {
this.currentValue = val; // value改变的时候,currentValue也改变
},

currentValue(newVal, oldVal) {
if (newVal <= this.max && newVal >= this.min) { // 新值合法
this.$emit('change', newVal, oldVal); // 触发 change 事件
this.$emit('input', newVal); // 触发 input 事件
} else { // 不合法就回复
this.currentValue = oldVal;
}
}
},

你可能感兴趣的:(Element分析(组件篇)—— InputNumber)