vue数字输入框

本文介绍了如何使用Vue.js和JavaScript构建一个数字输入框组件。首先讲解了emitter.js的作用,然后详细阐述了number.vue组件的实现,接着展示了index.js中的主要逻辑。最后,文章通过实际应用和展示效果图片来说明组件的使用方法和效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

eaae28014f374629a0c9aa609c135870.png

 1.emitter.JS

function broadcast (componentName, eventName, params) {
  this.$children.forEach(child => {
    var name = child.$options.componentName
    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params))
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]))
    }
  })
}

export default {
  methods: {
    dispatch (componentName, eventName, params) {
      var parent = this.$parent || this.$root
      var name = parent.$options.componentName

      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent
        if (parent) {
          name = parent.$options.componentName
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params))
      }
    },
    broadcast (componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params)
    }
  }
}

2.number.vue

<template>
  <div>
    <div class="el-number-input-wrap el-input" :class="{'is-disabled': this.inputDisabled}">
      <input
        :type="inputPositive"
        class="el-input__inner"
        :id="elementId"
        :class="inputClasses"
        :disabled="disabled"
        autoComplete="off"
        spellcheck="false"
        :autofocus="autofocus"
        @focus="handleFocus"
        @blur="handleBlur"
        @input="handleInput"
        @change="change"
        :readonly="readonly || !editable"
        :name="name"
        :value="formatterValue"
        :placeholder="placeholder"/>
    </div>
  </div>
</template>
<script>
import emitter from './emitter.js'
export default {
  name: 'Number',
  componentName: 'Number',
  mixins: [ emitter ],
  inheritAttrs: false,
  inject: {
    unForm: {
      default: ''
    },
    unFormItem: {
      default: ''
    }
  },
  props: {
    value: {
      type: [String, Number],
      default: null
    },
    max: {
      type: Number,
      default: Infinity
    },
    min: {
      type: Number,
      default: -Infinity
    },
    step: {
      type: Number,
      default: 1
    },
    activeChange: {
      type: Boolean,
      default: true
    },
    isnum: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    autofocus: {
      type: Boolean,
      default: false
    },
    readonly: {
      type: Boolean,
      default: false
    },
    editable: {
      type: Boolean,
      default: true
    },
    name: {
      type: String
    },
    precision: {
      type: Number
    },
    elementId: {
      type: String
    },
    formatter: {
      type: Function
    },
    parser: {
      type: Function
    },
    placeholder: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      focused: false,
      currentValue: this.value
    }
  },
  computed: {
    inputDisabled () {
      return this.disabled || (this.unForm || {}).disabled
    },
    inputClasses () {
      return 'el-number-input'
    },
    inputPositive () {
      if (this.isnum) return 'number'
    },
    precisionValue () {
      if (!this.currentValue) return this.currentValue
      if (this.precision) {
        var varStr = this.currentValue.toString()
        if (varStr.split('.').length === 1) {
          return this.currentValue
        } else {
          var len = varStr.split('.')[1].length
          if (len > this.precision) return this.currentValue.toFixed(this.precision)
          else return this.currentValue
        }
      } else {
        return this.currentValue
      }
    },
    formatterValue () {
      if (this.formatter && this.precisionValue !== null) {
        return this.formatter(this.precisionValue)
      } else {
        return this.precisionValue
      }
    },
    _unFormItemSize () {
      return (this.unFormItem || {}).unFormItemSize
    },
    validateState () {
      return this.unFormItem ? this.unFormItem.validateState : ''
    },
    needStatusIcon () {
      return this.unForm ? this.unForm.statusIcon : false
    },
    validateIcon () {
      return {
        validating: 'el-icon-loading',
        success: 'el-iocn-circle-check',
        error: 'el-icon-circle-close'
      }[this.validateState]
    }
  },
  methods: {
    preventDefault (e) {
      e.preventDefault()
    },
    setValue (val) {
      if (val && !isNaN(this.precision)) val = Number(val).toFixed(this.precision)

      if (val !== null) {
        if (val > this.max) {
          val = this.max && !isNaN(this.precision) ? Number(this.max).toFixed(this.precision) : this.max
        } else if (val < this.min) {
          val = this.min && !isNaN(this.precision) ? Number(this.min).toFixed(this.precision) : this.min
        }
      }

      this.$nextTick(() => {
        this.currentValue = val
        this.$emit('input', val)
        this.$emit('change', val)
        this.dispatch('ElFormItem', 'el.form.change', val)
      })
    },
    handleFocus (event) {
      this.focused = true
      this.$emit('focus', event)
    },
    handleBlur () {
      this.focused = false
      this.$emit('blur', event)
    },
    handleInput () {
      const value = event.target.value
      this.tmpValue = value
    },
    change (event) {
      if (event.type === 'input' && !this.activeChange) return
      let val = event.target.value.trim()
      if (this.parser) {
        val = this.parser(val)
      }

      const isEmptyString = val.length === 0
      if (isEmptyString) {
        this.setValue(null)
        return
      }

      // if (event.type === 'input' && val.match(/^[\+|\-]?\.?$|\.$/)) return
      if (event.type === 'input' && val.match(/^[+|-]?\.?$|\.$/)) return

      val = Number(val)

      if (!isNaN(val)) {
        this.currentValue = val
        event.target.value = this.currentValue
        this.setValue(val)
      } else {
        event.target.value = this.currentValue
      }
    },
    changeVal (val) {
      if (val === '' || val === null || val === undefined) {
        return
      }
      val = Number(val)
      if (!isNaN(val)) {
        const step = this.step
        this.upDisabled = val + step > this.max
        this.downDisabled = val - step < this.min
      } else {
        this.upDisabled = true
        this.downDisabled = true
      }
    }
  },
  mounted () {
    this.changeVal(this.currentValue)
  },
  watch: {
    value (val) {
      this.currentValue = val
    },
    currentValue (val) {
      this.changeVal(val)
    },
    min () {
      this.changeVal(this.currentValue)
    },
    max () {
      this.changeVal(this.currentValue)
    }
  }
}
</script>

3.index.js

import Number from './src/number.vue'

Number.install = function (Vue) {
  Vue.component(Number.name, Number)
}

export default Number

4.应用

<template>
  <div class="phone">
    <el-row :gutter="12">
      <el-col :span="12">
        <el-card shadow="hover">
          <div>
            <h3>基础用法</h3>
            <numbers :max="9999" :min="-9999" v-model="value1" placeholder="请输入数字"/>
            <div style="margin-top: 20px;">要使用它,只需要在el-number元素中使用v-model绑定变量即可,变量的初始值即为默认值,如果你只需要控制数值在某一范围内,可以设置min属性和max属性,不设置时,最小值为0</div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card shadow="hover">
          <div>
            <h3>只读状态</h3>
            <numbers :max="9999" :min="-9999" v-model="value2" placeholder="请输入数字" readonly/>
            <div style="margin-top: 20px;">readonly属性可设置组件为只读状态</div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <el-row :gutter="12">
      <el-col :span="12">
        <el-card shadow="hover">
          <div>
            <h3>禁用状态</h3>
            <numbers :max="9999" :min="-9999" v-model="value3" placeholder="请输入数字" disabled/>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card shadow="hover">
          <div>
            <h3>精度</h3>
            <numbers :max="9999" :min="-9999" v-model="value4" :precision="3" placeholder="请输入数字"/>
            <div style="margin-top: 20px;">precision属性可指定输入框数字的精度</div>
          </div>
        </el-card>
      </el-col>
    </el-row>
    <div style="margin-bottom: 20px;">
      <h3>Attributes</h3>
      <el-table
        :data="tableData"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="parameter"
          label="参数"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="type"
          label="类型"
          width="180">
        </el-table-column>
        <el-table-column
          prop="optionalValue"
          label="可选值"
          width="180">
        </el-table-column>
        <el-table-column
          prop="defaultValue"
          label="默认值"
          width="180">
        </el-table-column>
      </el-table>
      <h3>Number Events</h3>
      <el-table
        :data="tableData2"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="parameter"
          label="事件名称"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="callbackPar"
          label="回调参数">
        </el-table-column>
      </el-table>
      <h3>Number Methods</h3>
      <el-table
        :data="tableData3"
        stripe
        border
        style="width: 100%">
        <el-table-column
          prop="parameter"
          label="方法名"
          width="180">
        </el-table-column>
        <el-table-column
          prop="instructions"
          label="说明">
        </el-table-column>
        <el-table-column
          prop="callbackPar"
          label="参数">
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>

<script>
import numbers from '../../components/number/index.js'
export default {
  name: 'PhoneS',
  components: {
    numbers
  },
  data () {
    return {
      value1: '',
      value2: '123',
      value3: '123',
      value4: '',
      tableData: [
        {
          parameter: 'value',
          instructions: '绑定值',
          type: 'string/number',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'placeholder',
          instructions: '输入框占位文本',
          type: 'string',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'disabled',
          instructions: '禁用',
          type: 'boolean',
          optionalValue: '-',
          defaultValue: 'false'
        },
        {
          parameter: 'auto-complete',
          instructions: '原生属性,自动补全',
          type: 'string',
          optionalValue: 'on,off',
          defaultValue: 'off'
        },
        {
          parameter: 'name',
          instructions: '原生属性',
          type: 'string',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'readonly',
          instructions: '原生属性,是否只读',
          type: 'boolean',
          optionalValue: '-',
          defaultValue: 'false'
        },
        {
          parameter: 'max',
          instructions: '原生属性,设置最大值',
          type: 'number',
          optionalValue: '-',
          defaultValue: 'infinity'
        },
        {
          parameter: 'min',
          instructions: '原生属性,设置最小值',
          type: 'number',
          optionalValue: '-',
          defaultValue: '-infinity'
        },
        {
          parameter: 'autofocus',
          instructions: '原生属性,自动获取焦点',
          type: 'string',
          optionalValue: '-',
          defaultValue: '-'
        },
        {
          parameter: 'precision',
          instructions: '数字精度',
          type: 'number',
          optionalValue: '-',
          defaultValue: '-'
        }
      ],
      tableData2: [
        {
          parameter: 'blur',
          instructions: '在Number失去焦点的时候触发',
          callbackPar: '(event: Event)'
        },
        {
          parameter: 'focus',
          instructions: '在Number获得焦点的时候触发',
          callbackPar: '(event: Event)'
        }
      ],
      tableData3: [
        {
          parameter: 'blur',
          instructions: '使Number失去焦点',
          callbackPar: '-'
        },
        {
          parameter: 'focus',
          instructions: '使Number获得焦点',
          callbackPar: '-'
        }
      ]
    }
  },
  methods: {
    // 13213
  }
}
</script>

5.效果图

ba1ff241f8b44d518535e8ad9b3a1490.png

9fa1b9cf575e412582c336b5432c0e4c.png

 b0b2332c1fe243d5b0085f33839bced5.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shuleijia

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值