123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- <template>
- <div
- class="m-input-number"
- :class="[
- { 'is-disabled': inputNumberDisabled },
- { 'is-controls-right': controlsAtRight },
- inputNumberSize ? 'm-input-number--' + inputNumberSize : '',
- ]">
- <span
- v-if="controls"
- class="m-input-number__decrease"
- :class="{'is-disabled':minDisabled}"
- role="button"
- @click="handleClick('decrease')"
- >
- <i class="iconfont" :class="[controlsAtRight ? 'icon-arrow-down-bold' : 'icon-minus']"></i>
- </span>
- <input
- type="text"
- class="m-input__inner"
- :name="name"
- :value="inputVal"
- :disabled="inputNumberDisabled"
- @change="handleInputChange"
- @blur="handleBlur"
- @focus="handleFocus">
- <span
- v-if="controls"
- class="m-input-number__increase"
- :class="{'is-disabled':maxDisabled}"
- role="button"
- @click="handleClick('increase')"
- >
- <i class="iconfont" :class="[controlsAtRight ? 'icon-arrow-up-bold' : 'icon-add']"></i>
- </span>
- </div>
- </template>
- <script>
- export default {
- name: "mInputNumber"
- };
- </script>
- <script setup>
- import { ref,computed, getCurrentInstance } from 'vue-demi';
- const emit = defineEmits(['update:modelValue','change','focus','blur'])
- const props = defineProps({
- modelValue: [Number,String],
- name: String,
- step: {
- type: Number,
- default: 1
- },
- max: {
- type: Number,
- default: Infinity
- },
- min: {
- type: Number,
- default: -Infinity
- },
- disabled: {
- type: Boolean,
- default: false
- },
- stepStrictly: {
- type: Boolean,
- default: false
- },
- precision: {
- type: Number,
- validator(val) {
- return val >= 0 && val === parseInt(val, 10);
- }
- },
- controls: {
- type: Boolean,
- default: true
- },
- controlsPosition: {
- type: String,
- default: ''
- },
- size: String
- })
- const instance = getCurrentInstance();
- const inputVal = computed({
- get: () => props.modelValue,
- set: (newVal) => {
- let {min,max} = props
- let limit = [
- {
- validate: (value) => value <= min,
- res: min
- },
- {
- validate: (value) => value >= max,
- res: max
- },
- {
- validate: value => true,
- res: newVal * 1
- }
- ]
- let _val = limit.find(v => v.validate(newVal)).res
- // console.log('_val',_val);
- if(props.precision) {
- emit('update:modelValue',_val.toFixed(props.precision))
- emit('change',_val.toFixed(props.precision))
- } else {
- emit('update:modelValue',_val)
- emit('change',_val)
- }
- }
- })
- const controlsAtRight = computed(() => {
- return props.controls && props.controlsPosition === 'right'
- })
- const inputNumberSize = computed(() => {
- return props.size
- })
- const minDisabled = computed(() => {
- return props.disabled || props.modelValue <= props.min
- })
- const maxDisabled = computed(() => {
- return props.disabled || props.modelValue >= props.max
- })
- const inputNumberDisabled = computed(() => {
- return props.disabled
- })
- const handleInputChange = (e) => {
- let value = e.target.value;
- const newVal = Number(value);
- if (!isNaN(newVal) || value === '') {
- setCurrentValue(newVal)
- } else {
- // 如果输入的非数字,则保留之前的数据
- e.target.value = inputVal.value
- }
- }
- const setCurrentValue = (val) => {
- const newVal = verifyValue(val)
- emit('update:modelValue',newVal)
- emit('change',newVal)
- // 针对只有第一次改值生效的问题
- instance.proxy.$forceUpdate();
- }
- const verifyValue = (value) => {
- const { min, max, step, precision, stepStrictly } = props
- let newVal = Number(value)
- if(newVal <= min) newVal = min
- if(newVal >= max) newVal = max
- if (stepStrictly) {
- newVal = Math.round(newVal / step) * step
- }
- return newVal
- }
- const handleClick = (type) => {
- if(props.disabled) return
- if(type === 'decrease') {
- inputVal.value = Number(inputVal.value) - props.step
- } else {
- inputVal.value = Number(inputVal.value) + props.step
- }
- }
- const handleBlur = (e) => {
- emit('blur',e)
- }
- const handleFocus = (e) => {
- emit('focus',e)
- }
- </script>
- <style lang="scss" scoped>
- @import '../../styles/components/input-number.scss';
- </style>
|